public override EntityExpression GetEntityExpression(Expression root, MappingEntity entity) { // must be some complex type constructed from multiple columns var assignments = new List<EntityAssignment>(); foreach (MemberInfo mi in this.mapping.GetMappedMembers(entity)) { if (!this.mapping.IsAssociationRelationship(entity, mi)) { Expression me; if (this.mapping.IsNestedEntity(entity, mi)) { me = this.GetEntityExpression(root, this.mapping.GetRelatedEntity(entity, mi)); } else { me = this.GetMemberExpression(root, entity, mi); } if (me != null) { assignments.Add(new EntityAssignment(mi, me)); } } } return new EntityExpression(entity, this.BuildEntityExpression(entity, assignments)); }
public override Expression GetDeleteExpression(MappingEntity entity, Expression instance, LambdaExpression deleteCheck) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return base.GetDeleteExpression(entity, instance, deleteCheck); } var commands = new List<Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity).Reverse()) { TableExpression tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(table)); var where = this.GetIdentityCheck(tex, entity, instance); commands.Add(new DeleteCommand(tex, where)); } Expression block = new BlockCommand(commands); if (deleteCheck != null) { var test = this.GetEntityStateTest(entity, instance, deleteCheck); return new IFCommand(test, block, null); } return block; }
/// <summary> /// The query language specific type for the column /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual QueryType GetColumnType(MappingEntity entity, MemberInfo member) { string dbType = this.mapping.GetColumnDbType(entity, member); if (dbType != null) { return this.translator.Linguist.Language.TypeSystem.Parse(dbType); } return this.translator.Linguist.Language.TypeSystem.GetColumnType(TypeHelper.GetMemberType(member)); }
public override Expression GetDeleteExpression(MappingEntity entity, Expression instance, LambdaExpression deleteCheck) { TableExpression table = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(entity)); Expression where = null; if (instance != null) { where = this.GetIdentityCheck(table, entity, instance); } if (deleteCheck != null) { Expression row = this.GetEntityExpression(table, entity); Expression pred = DbExpressionReplacer.Replace(deleteCheck.Body, deleteCheck.Parameters[0], row); where = (where != null) ? where.And(pred) : pred; } return new DeleteCommand(table, where); }
/// <summary> /// The name of the corresponding database table /// </summary> /// <param name="rowType"></param> /// <returns></returns> public virtual string GetTableName(MappingEntity entity) { return entity.EntityType.Name; }
public override Expression GetPrimaryKeyQuery(MappingEntity entity, Expression source, Expression[] keys) { // make predicate ParameterExpression p = Expression.Parameter(entity.ElementType, "p"); Expression pred = null; var idMembers = this.GetPrimaryKeyMembers(entity).ToList(); if (idMembers.Count != keys.Length) { throw new InvalidOperationException("Incorrect number of primary key values"); } for (int i = 0, n = keys.Length; i < n; i++) { MemberInfo mem = idMembers[i]; Type memberType = TypeHelper.GetMemberType(mem); if (keys[i] != null && TypeHelper.GetNonNullableType(keys[i].Type) != TypeHelper.GetNonNullableType(memberType)) { throw new InvalidOperationException("Primary key value is wrong type"); } Expression eq = Expression.MakeMemberAccess(p, mem).Equal(keys[i]); pred = (pred == null) ? eq : pred.And(eq); } var predLambda = Expression.Lambda(pred, p); return Expression.Call(typeof(Queryable), "SingleOrDefault", new Type[] { entity.ElementType }, source, predLambda); }
/// <summary> /// The type of the entity on the other side of the relationship /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual MappingEntity GetRelatedEntity(MappingEntity entity, MemberInfo member) { Type relatedType = TypeHelper.GetElementType(TypeHelper.GetMemberType(member)); return this.GetEntity(relatedType); }
protected virtual Expression GetUpdateResult(MappingEntity entity, Expression instance, LambdaExpression selector) { var tq = this.GetQueryExpression(entity); Expression where = this.GetIdentityCheck(tq.Select, entity, instance); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], tq.Projector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tq.Select.Alias); return new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tq.Select, where), pc.Projector, Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)) ); }
public override object GetPrimaryKey(MappingEntity entity, object instance) { object firstKey = null; List<object> keys = null; foreach (var mi in this.GetPrimaryKeyMembers(entity)) { if (firstKey == null) { firstKey = mi.GetValue(instance); } else { if (keys == null) { keys = new List<object>(); keys.Add(firstKey); } keys.Add(mi.GetValue(instance)); } } if (keys != null) { return new CompoundKey(keys.ToArray()); } return firstKey; }
/// <summary> /// Determines if a property is generated on the server during insert /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual bool IsGenerated(MappingEntity entity, MemberInfo member) { return false; }
public override bool IsModified(MappingEntity entity, object instance, object original) { foreach (var mi in this.GetMappedMembers(entity)) { if (this.IsColumn(entity, mi)) { if (!object.Equals(mi.GetValue(instance), mi.GetValue(original))) return true; } } return false; }
/// <summary> /// The type declaration for the column in the provider's syntax /// </summary> /// <param name="entity"></param> /// <param name="member"></param> /// <returns>a string representing the type declaration or null</returns> public virtual string GetColumnDbType(MappingEntity entity, MemberInfo member) { return null; }
/// <summary> /// The name of the corresponding table column /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual string GetColumnName(MappingEntity entity, MemberInfo member) { return member.Name; }
public override object CloneEntity(MappingEntity entity, object instance) { var clone = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(entity.EntityType); foreach (var mi in this.GetMappedMembers(entity)) { if (this.IsColumn(entity, mi)) { mi.SetValue(clone, mi.GetValue(instance)); } } return clone; }
/// <summary> /// Returns the key members on the other side (related side) of the association /// </summary> /// <param name="entity"></param> /// <param name="member"></param> /// <returns></returns> public virtual IEnumerable<MemberInfo> GetAssociationRelatedKeyMembers(MappingEntity entity, MemberInfo member) { return new MemberInfo[] { }; }
protected virtual Expression GetIdentityCheck(Expression root, MappingEntity entity, Expression instance) { return this.mapping.GetMappedMembers(entity) .Where(m => this.mapping.IsPrimaryKey(entity, m)) .Select(m => this.GetMemberExpression(root, entity, m).Equal(Expression.MakeMemberAccess(instance, m))) .Aggregate((x, y) => x.And(y)); }
private bool IsNullRelationshipAssignment(MappingEntity entity, EntityAssignment assignment) { if (this.mapping.IsRelationship(entity, assignment.Member)) { var cex = assignment.Expression as ConstantExpression; if (cex != null && cex.Value == null) return true; } return false; }
private IEnumerable<ColumnAssignment> GetColumnAssignments(Expression table, Expression instance, MappingEntity entity, Func<MappingEntity, MemberInfo, bool> fnIncludeColumn) { foreach (var m in this.mapping.GetMappedMembers(entity)) { if (this.mapping.IsColumn(entity, m) && fnIncludeColumn(entity, m)) { yield return new ColumnAssignment( (ColumnExpression)this.GetMemberExpression(table, entity, m), Expression.MakeMemberAccess(instance, m) ); } } }
/// <summary> /// Determines if the property is an assocation relationship. /// </summary> /// <param name="entity"></param> /// <param name="member"></param> /// <returns></returns> public virtual bool IsAssociationRelationship(MappingEntity entity, MemberInfo member) { return false; }
public override bool IsRelationship(MappingEntity entity, MemberInfo member) { return this.IsAssociationRelationship(entity, member); }
/// <summary> /// Determines if a property is mapped onto a column /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual bool IsColumn(MappingEntity entity, MemberInfo member) { //return this.mapping.IsMapped(entity, member) && this.translator.Linguist.Language.IsScalar(TypeHelper.GetMemberType(member)); return this.IsMapped(entity, member); }
public abstract bool IsRelationshipTarget(MappingEntity entity, MemberInfo member);
/// <summary> /// Deterimines is a property is mapped onto a column or relationship /// </summary> /// <param name="member"></param> /// <returns></returns> public virtual bool IsMapped(MappingEntity entity, MemberInfo member) { return true; }
protected virtual DeclarationCommand GetGeneratedIdCommand(MappingEntity entity, List<MemberInfo> members, Dictionary<MemberInfo, Expression> map) { var columns = new List<ColumnDeclaration>(); var decls = new List<VariableDeclaration>(); var alias = new TableAlias(); foreach (var member in members) { Expression genId = this.translator.Linguist.Language.GetGeneratedIdExpression(member); var name = member.Name; var colType = this.GetColumnType(entity, member); columns.Add(new ColumnDeclaration(member.Name, genId, colType)); decls.Add(new VariableDeclaration(member.Name, colType, new ColumnExpression(genId.Type, colType, alias, member.Name))); if (map != null) { var vex = new VariableExpression(member.Name, TypeHelper.GetMemberType(member), colType); map.Add(member, vex); } } var select = new SelectExpression(alias, columns, null, null); return new DeclarationCommand(decls, select); }
/// <summary> /// Determines if a property represents or is part of the entities unique identity (often primary key) /// </summary> /// <param name="member"></param> /// <returns></returns> public override bool IsPrimaryKey(MappingEntity entity, MemberInfo member) { return false; }
protected virtual Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)); Expression where; DeclarationCommand genIdCommand = null; var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { if (map == null || !generatedIds.Any(m => map.ContainsKey(m))) { var localMap = new Dictionary<MemberInfo, Expression>(); genIdCommand = this.GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap); map = localMap; } // is this just a retrieval of one generated id member? var mex = selector.Body as MemberExpression; if (mex != null && this.mapping.IsPrimaryKey(entity, mex.Member) && this.mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { // just use the select from the genIdCommand return new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator ); } else { TableAlias alias = new TableAlias(); var colType = this.GetColumnType(entity, mex.Member); return new ProjectionExpression( new SelectExpression(alias, new[] { new ColumnDeclaration("", map[mex.Member], colType) }, null, null), new ColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, ""), aggregator ); } } where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = this.GetIdentityCheck(tex, entity, instance); } Expression typeProjector = this.GetEntityExpression(tex, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tableAlias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tex, where), pc.Projector, aggregator ); if (genIdCommand != null) { return new BlockCommand(genIdCommand, pe); } return pe; }
public abstract bool IsRelationshipSource(MappingEntity entity, MemberInfo member);
public override IEnumerable<EntityInfo> GetDependingEntities(MappingEntity entity, object instance) { foreach (var mi in this.GetMappedMembers(entity)) { if (this.IsRelationship(entity, mi) && this.IsRelationshipTarget(entity, mi)) { MappingEntity relatedEntity = this.GetRelatedEntity(entity, mi); var value = mi.GetValue(instance); if (value != null) { var list = value as IList; if (list != null) { foreach (var item in list) { if (item != null) { yield return new EntityInfo(item, relatedEntity); } } } else { yield return new EntityInfo(value, relatedEntity); } } } } }
/// <summary> /// Determines if a property can be part of an update operation /// </summary> /// <param name="entity"></param> /// <param name="member"></param> /// <returns></returns> public virtual bool IsUpdatable(MappingEntity entity, MemberInfo member) { return !this.IsPrimaryKey(entity, member); }
/// <summary> /// A sequence of all the mapped members /// </summary> /// <param name="rowType"></param> /// <returns></returns> public override IEnumerable<MemberInfo> GetMappedMembers(MappingEntity entity) { //Type type = entity.ElementType.IsInterface ? entity.EntityType : entity.ElementType; Type type = entity.EntityType; HashSet<MemberInfo> members = new HashSet<MemberInfo>(type.GetFields().Cast<MemberInfo>().Where(m => this.IsMapped(entity, m))); members.UnionWith(type.GetProperties().Cast<MemberInfo>().Where(m => this.IsMapped(entity, m))); return members.OrderBy(m => m.Name); }