Skip to content

Commit 2ec0dd7

Browse files
committed
add EntityTypeToken
1 parent adfd004 commit 2ec0dd7

File tree

5 files changed

+231
-16
lines changed

5 files changed

+231
-16
lines changed

Signum.Engine/Linq/ExpressionVisitor/QueryBinder.cs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,38 @@ public Expression BindMethodCall(MethodCallExpression m)
16661666
return tablePeriod;
16671667
}
16681668

1669+
if(m.Method.DeclaringType == typeof(TypeEntityExtensions) && m.Method.Name == nameof(TypeEntityExtensions.ToTypeEntity))
1670+
{
1671+
var arg = m.Arguments[0];
1672+
1673+
1674+
if (arg is TypeEntityExpression type)
1675+
{
1676+
var id = Condition(Expression.NotEqual(type.ExternalId, NullId(type.ExternalId.ValueType)),
1677+
ifTrue: Expression.Constant(TypeLogic.TypeToId.GetOrThrow(type.TypeValue).Object),
1678+
ifFalse: Expression.Constant(null, PrimaryKey.Type(typeof(TypeEntity)).Nullify()));
1679+
1680+
return new EntityExpression(typeof(TypeEntity), new PrimaryKeyExpression(id), null, null, null, null, null, false);
1681+
}
1682+
1683+
if (arg is TypeImplementedByExpression typeIB)
1684+
{
1685+
var id = typeIB.TypeImplementations.Aggregate(
1686+
(Expression)Expression.Constant(null, PrimaryKey.Type(typeof(TypeEntity)).Nullify()),
1687+
(acum, kvp) => Condition(Expression.NotEqual(kvp.Value, NullId(kvp.Value.Value.Type)),
1688+
ifTrue: Expression.Constant(TypeLogic.TypeToId.GetOrThrow(kvp.Key).Object),
1689+
ifFalse: acum));
1690+
1691+
return new EntityExpression(typeof(TypeEntity), new PrimaryKeyExpression(id), null, null, null, null, null, false);
1692+
}
1693+
1694+
if (arg is TypeImplementedByAllExpression typeIBA)
1695+
{
1696+
return new EntityExpression(typeof(TypeEntity), typeIBA.TypeColumn, null, null, null, null, null, false);
1697+
}
1698+
1699+
}
1700+
16691701
Expression PartialEval(Expression ee)
16701702
{
16711703
if (m.Method.IsExtensionMethod())
@@ -1678,20 +1710,22 @@ Expression PartialEval(Expression ee)
16781710
}
16791711
}
16801712

1681-
if (source is TypeEntityExpression type)
16821713
{
1683-
return Condition(Expression.NotEqual(type.ExternalId, NullId(type.ExternalId.ValueType)),
1684-
ifTrue: PartialEval(Expression.Constant(type.TypeValue)),
1685-
ifFalse: Expression.Constant(null, m.Type));
1686-
}
1714+
if (source is TypeEntityExpression type)
1715+
{
1716+
return Condition(Expression.NotEqual(type.ExternalId, NullId(type.ExternalId.ValueType)),
1717+
ifTrue: PartialEval(Expression.Constant(type.TypeValue)),
1718+
ifFalse: Expression.Constant(null, m.Type));
1719+
}
16871720

1688-
if(source is TypeImplementedByExpression typeIB)
1689-
{
1690-
return typeIB.TypeImplementations.Aggregate(
1691-
(Expression)Expression.Constant(null, m.Type),
1692-
(acum, kvp) => Condition(Expression.NotEqual(kvp.Value, NullId(kvp.Value.Value.Type)),
1693-
ifTrue: PartialEval(Expression.Constant(kvp.Key)),
1694-
ifFalse: acum));
1721+
if (source is TypeImplementedByExpression typeIB)
1722+
{
1723+
return typeIB.TypeImplementations.Aggregate(
1724+
(Expression)Expression.Constant(null, m.Type),
1725+
(acum, kvp) => Condition(Expression.NotEqual(kvp.Value, NullId(kvp.Value.Value.Type)),
1726+
ifTrue: PartialEval(Expression.Constant(kvp.Key)),
1727+
ifFalse: acum));
1728+
}
16951729
}
16961730

16971731
return m;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using Signum.Entities.Basics;
2+
using Signum.Utilities.Reflection;
3+
4+
namespace Signum.Entities.DynamicQuery;
5+
6+
7+
public class EntityTypeToken : QueryToken
8+
{
9+
QueryToken parent;
10+
public override QueryToken? Parent => parent;
11+
12+
internal EntityTypeToken(QueryToken parent)
13+
{
14+
this.parent = parent ?? throw new ArgumentNullException(nameof(parent));
15+
16+
this.Priority = 10;
17+
}
18+
19+
public override Type Type
20+
{
21+
get { return typeof(TypeEntity).BuildLite(); }
22+
}
23+
24+
public override string ToString()
25+
{
26+
return "[" + QueryTokenMessage.EntityType.NiceToString() + "]";
27+
}
28+
29+
public override string Key
30+
{
31+
get { return "[EntityType]"; }
32+
}
33+
34+
static MethodInfo miTypeEntity = ReflectionTools.GetMethodInfo(() => TypeEntityExtensions.ToTypeEntity(null!));
35+
36+
protected override Expression BuildExpressionInternal(BuildExpressionContext context)
37+
{
38+
Expression baseExpression = parent.BuildExpression(context);
39+
40+
Expression entityType = Expression.Property(baseExpression, "EntityType");
41+
42+
Expression typeEntity = Expression.Call(miTypeEntity, entityType);
43+
44+
return typeEntity.BuildLite();
45+
}
46+
47+
protected override List<QueryToken> SubTokensOverride(SubTokensOptions options)
48+
{
49+
return SubTokensBase(typeof(TypeEntity), options, GetImplementations());
50+
}
51+
52+
public override string? Format
53+
{
54+
get { return null; }
55+
}
56+
57+
public override string? Unit
58+
{
59+
get { return null; }
60+
}
61+
62+
public override Implementations? GetImplementations()
63+
{
64+
return Implementations.By(typeof(TypeEntity));
65+
}
66+
67+
public override string? IsAllowed()
68+
{
69+
var parentAllowed = this.parent.IsAllowed();
70+
var routeAllowed = GetPropertyRoute()!.IsAllowed();
71+
72+
if (parentAllowed.HasText() && routeAllowed.HasText())
73+
QueryTokenMessage.And.NiceToString().Combine(parentAllowed, routeAllowed);
74+
75+
return parentAllowed ?? routeAllowed;
76+
}
77+
78+
public override PropertyRoute? GetPropertyRoute()
79+
{
80+
return PropertyRoute.Root(typeof(TypeEntity));
81+
}
82+
83+
public override string NiceName()
84+
{
85+
return QueryTokenMessage._0Of1.NiceToString().FormatWith(QueryTokenMessage.EntityType.NiceToString(), parent.ToString());
86+
}
87+
88+
public override QueryToken Clone()
89+
{
90+
return new EntityTypeToken(parent.Clone());
91+
}
92+
}
93+

Signum.Entities/DynamicQuery/Tokens/QueryToken.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ protected List<QueryToken> SubTokensBase(Type type, SubTokensOptions options, Im
196196
if (cleanType.IsIEntity())
197197
{
198198
if (implementations!.Value.IsByAll)
199-
return ImplementedByAllSubTokens(this, type, options); // new[] { EntityPropertyToken.IdProperty(this) };
199+
return ImplementedByAllSubTokens(this, type, options).PreAnd(new EntityTypeToken(this)).ToList().AndHasValue(this); // new[] { EntityPropertyToken.IdProperty(this) };
200200

201201
var onlyType = implementations.Value.Types.Only();
202202

@@ -211,7 +211,7 @@ protected List<QueryToken> SubTokensBase(Type type, SubTokensOptions options, Im
211211
.NotNull()
212212
.Concat(EntityProperties(onlyType)).ToList().AndHasValue(this);
213213

214-
return implementations.Value.Types.Select(t => (QueryToken)new AsTypeToken(this, t)).ToList().AndHasValue(this);
214+
return implementations.Value.Types.Select(t => (QueryToken)new AsTypeToken(this, t)).PreAnd(new EntityTypeToken(this)).ToList().AndHasValue(this);
215215
}
216216

217217
if (type.IsEmbeddedEntity() || type.IsModelEntity())
@@ -696,5 +696,7 @@ public enum QueryTokenMessage
696696
RowId,
697697

698698
CellOperation,
699-
ContainerOfCellOperations
699+
ContainerOfCellOperations,
700+
[Description("Entity Type")]
701+
EntityType
700702
}

Signum.React/Scripts/Signum.Entities.DynamicQuery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ export module QueryTokenMessage {
133133
export const RowId = new MessageKey("QueryTokenMessage", "RowId");
134134
export const CellOperation = new MessageKey("QueryTokenMessage", "CellOperation");
135135
export const ContainerOfCellOperations = new MessageKey("QueryTokenMessage", "ContainerOfCellOperations");
136+
export const EntityType = new MessageKey("QueryTokenMessage", "EntityType");
136137
}
137138

138139
export const RefreshMode = new EnumType<RefreshMode>("RefreshMode");

Signum.Test/LinqProvider/GetTypeAndNewTest.cs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Signum.Entities.Basics;
12
using Signum.Utilities.DataStructures;
23
using System.IO;
34
using System.Text;
@@ -101,7 +102,91 @@ public void TestIsNew()
101102
select new { f.Name }).ToList();
102103

103104
Assert.NotEmpty(list);
104-
}
105+
}
106+
107+
[Fact]
108+
public void SelectToTypeEntity()
109+
{
110+
var list = (from f in Database.Query<ArtistEntity>()
111+
select f.GetType().ToTypeEntity())
112+
.ToList();
105113

114+
Assert.NotEmpty(list);
115+
}
116+
117+
[Fact]
118+
public void WhereToTypeEntity()
119+
{
120+
var list = (from f in Database.Query<ArtistEntity>()
121+
where f.GetType().ToTypeEntity().Is(typeof(ArtistEntity).ToTypeEntity())
122+
select f)
123+
.ToList();
124+
125+
126+
Assert.NotEmpty(list);
127+
}
128+
129+
[Fact]
130+
public void SelectToTypeEntityIB()
131+
{
132+
var list = (from f in Database.Query<BandEntity>()
133+
select f.LastAward!.GetType().ToTypeEntity())
134+
.ToList();
135+
136+
Assert.NotEmpty(list);
137+
}
138+
139+
[Fact]
140+
public void WhereToTypeEntityIB()
141+
{
142+
var list = (from f in Database.Query<BandEntity>()
143+
where f.LastAward!.GetType().ToTypeEntity().Is(typeof(GrammyAwardEntity).ToTypeEntity())
144+
select f)
145+
.ToList();
106146

147+
Assert.NotEmpty(list);
148+
}
149+
150+
[Fact]
151+
public void WhereToTypeEntityIBGroupBy()
152+
{
153+
var list = (from f in Database.Query<BandEntity>()
154+
group f by f.LastAward!.GetType().ToTypeEntity() into g
155+
select new { g.Key, Count = g.Count() })
156+
.ToList();
157+
158+
Assert.NotEmpty(list);
159+
}
160+
161+
[Fact]
162+
public void SelectToTypeEntityIBA()
163+
{
164+
var list = (from f in Database.Query<NoteWithDateEntity>()
165+
select f.Target.GetType().ToTypeEntity())
166+
.ToList();
167+
168+
Assert.NotEmpty(list);
169+
}
170+
171+
[Fact]
172+
public void WhereToTypeEntityIBA()
173+
{
174+
var list = (from f in Database.Query<NoteWithDateEntity>()
175+
where f.Target.GetType().ToTypeEntity().Is(typeof(ArtistEntity).ToTypeEntity())
176+
select f)
177+
.ToList();
178+
179+
Assert.NotEmpty(list);
180+
}
181+
182+
[Fact]
183+
public void WhereToTypeEntityIBAGroupBy()
184+
{
185+
var list = (from f in Database.Query<NoteWithDateEntity>()
186+
group f by f.Target.GetType().ToTypeEntity() into g
187+
select new { g.Key, Count = g.Count() })
188+
.ToList();
189+
190+
Assert.NotEmpty(list);
191+
}
107192
}

0 commit comments

Comments
 (0)