PageRenderTime 113ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Signum.Engine/Schema/Schema.Expressions.cs

http://signum.codeplex.com
C# | 236 lines | 193 code | 43 blank | 0 comment | 12 complexity | cc526da695ed126d44c6b9a7701f23db MD5 | raw file
Possible License(s): LGPL-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reflection;
  6. using System.Data;
  7. using System.IO;
  8. using Microsoft.SqlServer.Server;
  9. using Signum.Utilities;
  10. using Signum.Entities;
  11. using Signum.Engine;
  12. using System.Linq.Expressions;
  13. using System.Diagnostics;
  14. using System.Collections.ObjectModel;
  15. using Signum.Engine.Linq;
  16. using Signum.Entities.Reflection;
  17. using Signum.Engine.Properties;
  18. using Signum.Utilities.Reflection;
  19. namespace Signum.Engine.Maps
  20. {
  21. public partial class Table
  22. {
  23. internal Expression GetProjectorExpression(Alias tableAlias, QueryBinder binder)
  24. {
  25. var bindings = Bindings(tableAlias, binder);
  26. if (IsView)
  27. {
  28. return new EmbeddedEntityExpression(this.Type, null, bindings, null);
  29. }
  30. else
  31. {
  32. Expression id = bindings.FirstEx(a => ReflectionTools.FieldEquals(a.FieldInfo, EntityExpression.IdField)).Binding;
  33. Schema.Current.AssertAllowed(Type);
  34. var result = new EntityExpression(this.Type, id, tableAlias, bindings);
  35. return result;
  36. }
  37. }
  38. internal ReadOnlyCollection<FieldBinding> Bindings(Alias tableAlias, QueryBinder binder)
  39. {
  40. List<FieldBinding> result = new List<FieldBinding>();
  41. var id = GetIdExpression(tableAlias);
  42. if (id != null)
  43. result.Add(new FieldBinding(Table.fiId, id));
  44. foreach (var ef in this.Fields.Values)
  45. {
  46. var fi = ef.FieldInfo;
  47. if (!ReflectionTools.FieldEquals(fi, fiId))
  48. result.Add(new FieldBinding(fi, ef.Field.GetExpression(tableAlias, binder, id)));
  49. }
  50. return result.ToReadOnly();
  51. }
  52. internal Expression GetIdExpression(Alias alias)
  53. {
  54. var field = Fields.TryGetC(Table.fiId.Name);
  55. if (field == null)
  56. return null;
  57. return field.Field.GetExpression(alias, null, null);
  58. }
  59. }
  60. public partial class RelationalTable
  61. {
  62. internal ColumnExpression RowIdExpression(Alias tableAlias)
  63. {
  64. return new ColumnExpression(typeof(int), tableAlias, ((IColumn)this.PrimaryKey).Name);
  65. }
  66. internal ColumnExpression BackColumnExpression(Alias tableAlias)
  67. {
  68. return new ColumnExpression(BackReference.ReferenceType(), tableAlias, BackReference.Name);
  69. }
  70. internal Expression FieldExpression(Alias tableAlias, QueryBinder binder)
  71. {
  72. return Field.GetExpression(tableAlias, binder, null);
  73. }
  74. internal Expression GetProjectorExpression(Alias tableAlias, QueryBinder binder)
  75. {
  76. Schema.Current.AssertAllowed(this.BackReference.ReferenceTable.Type);
  77. Type elementType = typeof(MListElement<,>).MakeGenericType(BackReference.FieldType, Field.FieldType);
  78. return new MListElementExpression(
  79. RowIdExpression(tableAlias) ,
  80. (EntityExpression)this.BackReference.GetExpression(tableAlias, binder, null),
  81. this.Field.GetExpression(tableAlias, binder, null), this);
  82. }
  83. }
  84. public static partial class ColumnExtensions
  85. {
  86. public static Type ReferenceType(this IColumn columna)
  87. {
  88. Debug.Assert(columna.SqlDbType == SqlBuilder.PrimaryKeyType);
  89. return columna.Nullable ? typeof(int?) : typeof(int);
  90. }
  91. }
  92. public abstract partial class Field
  93. {
  94. internal abstract Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id);
  95. }
  96. public partial class FieldPrimaryKey
  97. {
  98. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  99. {
  100. return new ColumnExpression(typeof(int), tableAlias, this.Name);
  101. }
  102. }
  103. public partial class FieldValue
  104. {
  105. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  106. {
  107. return new ColumnExpression(this.FieldType, tableAlias, this.Name);
  108. }
  109. }
  110. public partial class FieldReference
  111. {
  112. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  113. {
  114. Type cleanType = IsLite ? Lite.Extract(FieldType) : FieldType;
  115. var result = new EntityExpression(cleanType, new ColumnExpression(this.ReferenceType(), tableAlias, Name), null, null);
  116. if(this.IsLite)
  117. return binder.MakeLite(this.FieldType, result, null);
  118. else
  119. return result;
  120. }
  121. }
  122. public partial class FieldEnum
  123. {
  124. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  125. {
  126. return Expression.Convert(new ColumnExpression(this.ReferenceType(), tableAlias, Name), FieldType);
  127. }
  128. }
  129. public partial class FieldMList
  130. {
  131. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  132. {
  133. return new MListExpression(FieldType, id, RelationalTable); // keep back id empty for some seconds
  134. }
  135. }
  136. public partial class FieldEmbedded
  137. {
  138. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  139. {
  140. var bindings = (from kvp in EmbeddedFields
  141. let fi = kvp.Value.FieldInfo
  142. select new FieldBinding(fi, kvp.Value.Field.GetExpression(tableAlias, binder, null))).ToReadOnly();
  143. ColumnExpression hasValue = HasValue == null ? null : new ColumnExpression(typeof(bool), tableAlias, HasValue.Name);
  144. return new EmbeddedEntityExpression(this.FieldType, hasValue, bindings, this);
  145. }
  146. internal EmbeddedEntityExpression FromConstantExpression(ConstantExpression contant, QueryBinder tools)
  147. {
  148. var value = contant.Value;
  149. var bindings = (from kvp in EmbeddedFields
  150. let fi = kvp.Value.FieldInfo
  151. select new FieldBinding(fi,
  152. tools.VisitConstant(kvp.Value.Getter(value), kvp.Value.FieldInfo.FieldType))).ToReadOnly();
  153. return new EmbeddedEntityExpression(this.FieldType, Expression.Constant(true), bindings, this);
  154. }
  155. internal EmbeddedEntityExpression FromMemberInitiExpression(MemberInitExpression mie, QueryBinder tools)
  156. {
  157. var dic = mie.Bindings.OfType<MemberAssignment>().ToDictionary(a=>(a.Member as FieldInfo ?? Reflector.FindFieldInfo(mie.Type, (PropertyInfo)a.Member)).Name, a=>a.Expression);
  158. var bindings = (from kvp in EmbeddedFields
  159. let fi = kvp.Value.FieldInfo
  160. select new FieldBinding(fi,
  161. dic.TryGetC(fi.Name) ?? tools.VisitConstant(Expression.Constant(null, fi.FieldType), fi.FieldType))).ToReadOnly();
  162. return new EmbeddedEntityExpression(this.FieldType, Expression.Constant(true), bindings, this);
  163. }
  164. }
  165. public partial class FieldImplementedBy
  166. {
  167. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  168. {
  169. var implementations = (from kvp in ImplementationColumns
  170. select new Linq.ImplementationColumn(kvp.Key,
  171. new EntityExpression(kvp.Key, new ColumnExpression(kvp.Value.ReferenceType(), tableAlias, kvp.Value.Name), null, null))
  172. ).ToReadOnly();
  173. var result = new ImplementedByExpression(IsLite ? Lite.Extract(FieldType) : FieldType, implementations);
  174. if (this.IsLite)
  175. return binder.MakeLite(this.FieldType, result, null);
  176. else
  177. return result;
  178. }
  179. }
  180. public partial class FieldImplementedByAll
  181. {
  182. internal override Expression GetExpression(Alias tableAlias, QueryBinder binder, Expression id)
  183. {
  184. Expression result = new ImplementedByAllExpression(IsLite ? Lite.Extract(FieldType) : FieldType,
  185. new ColumnExpression(Column.ReferenceType(), tableAlias, Column.Name),
  186. new TypeImplementedByAllExpression(new ColumnExpression(Column.ReferenceType(), tableAlias, ColumnTypes.Name)));
  187. if (this.IsLite)
  188. return binder.MakeLite(this.FieldType, result, null);
  189. else
  190. return result;
  191. }
  192. }
  193. }