예제 #1
0
		private void InitSpecialMember(MetaDataMember mm)
		{
			// Can only have one auto gen member that is also an identity member,
			// except if that member is a computed column (since they are implicitly auto gen)
			if(mm.IsDbGenerated && mm.IsPrimaryKey && string.IsNullOrEmpty(mm.Expression))
			{
				if(this.dbGeneratedIdentity != null)
					throw Error.TwoMembersMarkedAsPrimaryKeyAndDBGenerated(mm.Member, this.dbGeneratedIdentity.Member);
				this.dbGeneratedIdentity = mm;
			}
			if(mm.IsPrimaryKey && !MappingSystem.IsSupportedIdentityType(mm.Type))
			{
				throw Error.IdentityClrTypeNotSupported(mm.DeclaringType, mm.Name, mm.Type);
			}
			if(mm.IsVersion)
			{
				if(this.version != null)
					throw Error.TwoMembersMarkedAsRowVersion(mm.Member, this.version.Member);
				this.version = mm;
			}
			if(mm.IsDiscriminator)
			{
				if(this.discriminator != null)
					throw Error.TwoMembersMarkedAsInheritanceDiscriminator(mm.Member, this.discriminator.Member);
				this.discriminator = mm;
			}
		}
 public AttributedMetaAssociation(MemberInfo member, AssociationAttribute attribute, MetaDataMember metaDataMember)
 {
     memberInfo = member;
     associationAttribute = attribute;
     thisMember = metaDataMember;
     Load();
 }
 internal MemberChangeConflict(ObjectChangeConflict conflict, MetaDataMember metaMember) {
     this.conflict = conflict;            
     this.metaMember = metaMember;
     this.originalValue = metaMember.StorageAccessor.GetBoxedValue(conflict.Original);
     this.databaseValue = metaMember.StorageAccessor.GetBoxedValue(conflict.Database);
     this.currentValue = metaMember.StorageAccessor.GetBoxedValue(conflict.TrackedObject.Current);
 }
 public virtual void SetOtherKey(string literalOtherKey, MetaTable thisTable, MetaTable otherTable, MetaDataMember otherAssociationMember)
 {
     var comma = new[] { ',' };
     var otherKeysList = new List<MetaDataMember>();
     if (literalOtherKey != null)
     {
         foreach (var otherKeyRaw in literalOtherKey.Split(comma, StringSplitOptions.RemoveEmptyEntries))
         {
             var otherKey = otherKeyRaw.Trim();
             //we need to revisit this code - it has caused problems on both MySql and Pgsql
             MemberInfo[] otherKeyFields = otherTable.RowType.Type.GetMember(otherKey);
             if (otherKeyFields.Length == 0)
             {
                 string msg = "ERROR L57 Database contains broken join information."
                     + " thisTable=" + thisTable.TableName
                     + " otherTable=" + otherTable.TableName
                     + " orphanKey=" + literalOtherKey;
                 throw new InvalidOperationException(msg);
             }
             var keyMember = otherKeyFields[0];
             otherKeysList.Add(new AttributedColumnMetaDataMember(keyMember, GetColumnAttribute(keyMember),
                                                                  thisTable.RowType));
         }
     }
     otherKeys = new ReadOnlyCollection<MetaDataMember>(otherKeysList);
     otherMember = otherAssociationMember;
 }
예제 #5
0
		private void ValidatePrimaryKeyMember(MetaDataMember mm)
		{
			//if the type is a sub-type, no member in the type can be primary key
			if(mm.IsPrimaryKey && this.inheritanceRoot != this && mm.Member.DeclaringType == this.type)
			{
				throw (Error.PrimaryKeyInSubTypeNotSupported(this.type.Name, mm.Name));
			}
		}
예제 #6
0
 private void ValidatePrimaryKeyMember(MetaDataMember metaDataMember)
 {
     // if the type is a sub-type, no member declared in the type can be primary key
     if (metaDataMember.IsPrimaryKey && inheritanceRoot != this && metaDataMember.Member.DeclaringType == type)
     {
         throw Error.PrimaryKeyInSubTypeNotSupported(type.Name, metaDataMember.Name);
     }
 }
예제 #7
0
 private void ValidatePrimaryKeyMember(MetaDataMember mm)
 {
     //if the type is a sub-type, no member in the type can be primary key
     if (mm.IsPrimaryKey && this.inheritanceRoot != this && mm.Member.DeclaringType == this.type)
     {
         throw (Error.PrimaryKeyInSubTypeNotSupported(this.type.Name, mm.Name));
     }
 }
        internal AttributedMetaAssociation(AttributedMetaDataMember member, AssociationAttribute attr)
        {
            thisMember = member;

            isMany = TypeSystem.IsSequenceType(thisMember.Type);
            var otherEntityType = isMany ? TypeSystem.GetElementType(thisMember.Type) : thisMember.Type;

            otherType = thisMember.DeclaringType.Model.GetMetaType(otherEntityType);
            thisKey   = attr.ThisKey == null ?
                        thisMember.DeclaringType.IdentityMembers :
                        MakeKeys(thisMember.DeclaringType, attr.ThisKey);
            otherKey             = attr.OtherKey == null ? otherType.IdentityMembers : MakeKeys(otherType, attr.OtherKey);
            thisKeyIsPrimaryKey  = AreEqual(thisKey, thisMember.DeclaringType.IdentityMembers);
            otherKeyIsPrimaryKey = AreEqual(otherKey, otherType.IdentityMembers);
            isForeignKey         = attr.IsForeignKey;

            isUnique     = attr.IsUnique;
            deleteRule   = attr.DeleteRule;
            deleteOnNull = attr.DeleteOnNull;

            // if any key members are not nullable, the association is not nullable
            isNullable = true;
            foreach (var thisKeyMember in thisKey)
            {
                if (!thisKeyMember.CanBeNull)
                {
                    isNullable = false;
                    break;
                }
            }

            // validate DeleteOnNull specification
            if (deleteOnNull && (!isForeignKey || isMany || isNullable))
            {
                throw Error.InvalidDeleteOnNullSpecification(member);
            }

            if ((thisKey.Count != otherKey.Count) && (thisKey.Count > 0) && (otherKey.Count > 0))
            {
                throw Error.MismatchedThisKeyOtherKey(member.Name, member.DeclaringType.Name);
            }

            // determine reverse reference member
            foreach (var otherTypePersistentMember in otherType.PersistentDataMembers)
            {
                var otherTypeMemberAssociationAttribute = ((AttributedMetaModel)thisMember.DeclaringType.Model)
                                                          .TryGetAssociationAttribute(otherTypePersistentMember.Member);
                if ((otherTypeMemberAssociationAttribute != null) &&
                    (otherTypePersistentMember != thisMember) &&
                    (otherTypeMemberAssociationAttribute.Name == attr.Name))
                {
                    otherMember = otherTypePersistentMember;
                    break;
                }
            }

            //validate the number of ThisKey columns is the same as the number of OtherKey columns
        }
 public ColumnExpression(TableExpression table, MetaDataMember metaData)
     : base(ExpressionType, metaData.Member.GetMemberType()) // memberInfo.GetMemberType())
 {
     Table = table;
     Name = metaData.MappedName;
     MemberInfo = metaData.Member;
     StorageInfo = metaData.StorageMember;
     RequestIndex = -1; // unused
 }
예제 #10
0
        internal AttributedMetaAssociation(AttributedMetaDataMember member, AssociationAttribute attr)
        {
            this.thisMember = member;

            this.isMany = TypeSystem.IsSequenceType(this.thisMember.Type);
            Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;

            this.otherType            = this.thisMember.DeclaringType.Model.GetMetaType(ot);
            this.thisKey              = (attr.ThisKey != null) ? MakeKeys(this.thisMember.DeclaringType, attr.ThisKey) : this.thisMember.DeclaringType.IdentityMembers;
            this.otherKey             = (attr.OtherKey != null) ? MakeKeys(otherType, attr.OtherKey) : this.otherType.IdentityMembers;
            this.thisKeyIsPrimaryKey  = AreEqual(this.thisKey, this.thisMember.DeclaringType.IdentityMembers);
            this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
            this.isForeignKey         = attr.IsForeignKey;

            this.isUnique     = attr.IsUnique;
            this.deleteRule   = attr.DeleteRule;
            this.deleteOnNull = attr.DeleteOnNull;

            // if any key members are not nullable, the association is not nullable
            foreach (MetaDataMember mm in thisKey)
            {
                if (!mm.CanBeNull)
                {
                    this.isNullable = false;
                    break;
                }
            }

            // validate DeleteOnNull specification
            if (deleteOnNull == true)
            {
                if (!(isForeignKey && !isMany && !isNullable))
                {
                    throw Error.InvalidDeleteOnNullSpecification(member);
                }
            }

            //validate the number of ThisKey columns is the same as the number of OtherKey columns
            if (this.thisKey.Count != this.otherKey.Count && this.thisKey.Count > 0 && this.otherKey.Count > 0)
            {
                throw Error.MismatchedThisKeyOtherKey(member.Name, member.DeclaringType.Name);
            }

            // determine reverse reference member
            foreach (MetaDataMember omm in this.otherType.PersistentDataMembers)
            {
                AssociationAttribute oattr = (AssociationAttribute)Attribute.GetCustomAttribute(omm.Member, typeof(AssociationAttribute));
                if (oattr != null)
                {
                    if (omm != this.thisMember && oattr.Name == attr.Name)
                    {
                        this.otherMember = omm;
                        break;
                    }
                }
            }
        }
		internal AttributedMetaAssociation(AttributedMetaDataMember member, AssociationAttribute attr)
		{
			this.thisMember = member;

			this.isMany = TypeSystem.IsSequenceType(this.thisMember.Type);
			Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;
			this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot);
			this.thisKey = (attr.ThisKey != null) ? MakeKeys(this.thisMember.DeclaringType, attr.ThisKey) : this.thisMember.DeclaringType.IdentityMembers;
			this.otherKey = (attr.OtherKey != null) ? MakeKeys(otherType, attr.OtherKey) : this.otherType.IdentityMembers;
			this.thisKeyIsPrimaryKey = AreEqual(this.thisKey, this.thisMember.DeclaringType.IdentityMembers);
			this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
			this.isForeignKey = attr.IsForeignKey;

			this.isUnique = attr.IsUnique;
			this.deleteRule = attr.DeleteRule;
			this.deleteOnNull = attr.DeleteOnNull;

			// if any key members are not nullable, the association is not nullable
			foreach(MetaDataMember mm in thisKey)
			{
				if(!mm.CanBeNull)
				{
					this.isNullable = false;
					break;
				}
			}

			// validate DeleteOnNull specification
			if(deleteOnNull == true)
			{
				if(!(isForeignKey && !isMany && !isNullable))
				{
					throw Error.InvalidDeleteOnNullSpecification(member);
				}
			}

			//validate the number of ThisKey columns is the same as the number of OtherKey columns
			if(this.thisKey.Count != this.otherKey.Count && this.thisKey.Count > 0 && this.otherKey.Count > 0)
			{
				throw Error.MismatchedThisKeyOtherKey(member.Name, member.DeclaringType.Name);
			}

			// determine reverse reference member
			foreach(MetaDataMember omm in this.otherType.PersistentDataMembers)
			{
				AssociationAttribute oattr = (AssociationAttribute)Attribute.GetCustomAttribute(omm.Member, typeof(AssociationAttribute));
				if(oattr != null)
				{
					if(omm != this.thisMember && oattr.Name == attr.Name)
					{
						this.otherMember = omm;
						break;
					}
				}
			}
		}
예제 #12
0
		internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable<SqlExpression> keyExpressions, SqlExpression expansion, Expression sourceExpression)
			: base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
			this.id = id;
			this.rowType = rowType;
			this.expansion = expansion;
			this.expression = expression;
			this.member = member;
			this.keyExpressions = new List<SqlExpression>();
			if (keyExpressions != null)
				this.keyExpressions.AddRange(keyExpressions);
			}
예제 #13
0
		public DLinqColumnProvider (TableProvider owner, MetaDataMember meta)
			: base (owner)
		{
			if (owner == null)
				throw new ArgumentNullException ("owner");
			if (meta == null)
				throw new ArgumentNullException ("meta");

			// FIXME: fill more
			Name = meta.Name;
			Nullable = meta.CanBeNull;
		}
        /// <summary>
        /// Returns an AssociationAttribute for the specified association member
        /// </summary>
        /// <param name="member">The metadata member corresponding to the association member</param>
        /// <returns>The Association attribute</returns>
        public System.ComponentModel.DataAnnotations.AssociationAttribute CreateAssociationAttribute(MetaDataMember member)
        {
            MetaAssociation metaAssociation = member.Association;

            string associationName = this.GetAssociationName(metaAssociation);
            string thisKey = TypeDescriptionContextBase.FormatMemberList(metaAssociation.ThisKey.Select(p => p.Name));
            string otherKey = TypeDescriptionContextBase.FormatMemberList(metaAssociation.OtherKey.Select(p => p.Name));
            System.ComponentModel.DataAnnotations.AssociationAttribute assocAttrib = new System.ComponentModel.DataAnnotations.AssociationAttribute(associationName, thisKey, otherKey);
            assocAttrib.IsForeignKey = metaAssociation.IsForeignKey;

            return assocAttrib;
        }
예제 #15
0
		internal SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)
			: base(SqlNodeType.Column, clrType, sourceExpression) {
			if (typeof(Type).IsAssignableFrom(clrType))
				throw Error.ArgumentWrongValue("clrType");
			this.Name = name;
			this.member = member;
			this.Expression = expr;
			this.Ordinal = -1;
			if (sqlType == null)
				throw Error.ArgumentNull("sqlType");
			this.sqlType = sqlType;
			System.Diagnostics.Debug.Assert(sqlType.CanBeColumn);
			}
 public DLinqColumnProvider(DLinqTableProvider table, MetaDataMember member)
     : base(table) {
     Member = member;
     Name = member.Name;
     ColumnType = GetMemberType(member);
     IsPrimaryKey = member.IsPrimaryKey;
     IsGenerated = member.IsDbGenerated;
     _isAssociation = member.IsAssociation;
     IsCustomProperty = !member.IsAssociation && Member.DbType == null;
     Nullable = Member.IsAssociation ? Member.Association.IsNullable : Member.CanBeNull;
     MaxLength = ProcessMaxLength(ColumnType, Member.DbType);
     IsSortable = ProcessIsSortable(ColumnType, Member.DbType);
 }
        private void AddColumn(DLinqDataModelProvider dataModel, MetaDataMember member, PropertyInfo propInfo) {
            var publicGetAccessor = propInfo.GetGetMethod();
            if (publicGetAccessor == null) {
                // the property at least needs to have a public getter, otherwise databinding will not work
                return;
            }

            DLinqColumnProvider column = new DLinqColumnProvider(this, member);
            _columns.Add(column);

            if (!dataModel.ColumnLookup.ContainsKey(propInfo))
                dataModel.ColumnLookup[propInfo] = column;
        }
예제 #18
0
        public AttributedMetaAssociation(MemberInfo member, AssociationAttribute attribute, MetaDataMember metaDataMember)
        {
            _memberInfo = member;
            _associationAttribute = attribute;
            _thisMember = metaDataMember;
			// The bug described here:
			// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=376669
			// says that under certain conditions, there's a bug where _otherMember == _thisMember
			// Not only is there no point in reproducing a MS bug, it's not as simple as simply setting _otherMember = metaDataMember
			Type otherType = _memberInfo.GetFirstInnerReturnType();
			string associationName = member.GetAttribute<AssociationAttribute>().Name;
			AttributedMetaType ownedMetaType = metaDataMember.DeclaringType.Model.GetMetaType(otherType) as AttributedMetaType;

			if ( ownedMetaType == null )
				throw new InvalidOperationException("Key in referenced table is of a different SQL MetaData provider");

			_otherMember = ownedMetaType.AssociationsLookup[otherType.GetMembers().Where(m => (AttributeNameNullCheck(m.GetAttribute<AssociationAttribute>()) == associationName) && (m != member)).Single()];
        }
예제 #19
0
		/// <summary>
		/// Given a MetaType and a set of key fields, return the set of MetaDataMembers
		/// corresponding to the key.
		/// </summary>
		protected static ReadOnlyCollection<MetaDataMember> MakeKeys(MetaType mtype, string keyFields)
		{
			string[] names = keyFields.Split(keySeparators);
			MetaDataMember[] members = new MetaDataMember[names.Length];
			for(int i = 0; i < names.Length; i++)
			{
				names[i] = names[i].Trim();
				MemberInfo[] rmis = mtype.Type.GetMember(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if(rmis == null || rmis.Length != 1)
				{
					throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
				}
				members[i] = mtype.GetDataMember(rmis[0]);
				if(members[i] == null)
				{
					throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
				}
			}
			return new List<MetaDataMember>(members).AsReadOnly();
		}
예제 #20
0
 /// <summary>
 /// Given a MetaType and a set of key fields, return the set of MetaDataMembers
 /// corresponding to the key.
 /// </summary>
 protected static ReadOnlyCollection <MetaDataMember> MakeKeys(MetaType mtype, string keyFields)
 {
     string[]         names   = keyFields.Split(keySeparators);
     MetaDataMember[] members = new MetaDataMember[names.Length];
     for (int i = 0; i < names.Length; i++)
     {
         names[i] = names[i].Trim();
         MemberInfo[] rmis = mtype.Type.GetMember(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
         if (rmis == null || rmis.Length != 1)
         {
             throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
         }
         members[i] = mtype.GetDataMember(rmis[0]);
         if (members[i] == null)
         {
             throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
         }
     }
     return(new List <MetaDataMember>(members).AsReadOnly());
 }
예제 #21
0
 private void InitOther()
 {
     if (this.otherType == null)
     {
         Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;
         this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot);
         System.Diagnostics.Debug.Assert(this.otherType.IsEntity);
         this.otherKey = (assocMap.OtherKey != null)
                                 ? MakeKeys(this.otherType, this.assocMap.OtherKey)
                                 : this.otherType.IdentityMembers;
         this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
         foreach (MetaDataMember omm in this.otherType.DataMembers)
         {
             if (omm.IsAssociation && omm != this.thisMember && omm.MappedName == this.thisMember.MappedName)
             {
                 this.otherMember = omm;
                 break;
             }
         }
     }
 }
예제 #22
0
        public string CreateColomnSQL(
            MetaTable table,
            MetaDataMember member)
        {
            StringBuilder sqlText = new StringBuilder();

            if (member.IsPrimaryKey)
            {
                sqlText.AppendFormat("{0} INTEGER PRIMARY KEY AUTOINCREMENT ", member.MappedName);
            }
            else
            {
                sqlText.AppendFormat("{0} {1} ", member.MappedName, member.DbType);
            }

            if (!member.CanBeNull)
            {
                sqlText.Append("NOT NULL");
            }

            return sqlText.ToString();
        }
예제 #23
0
        public string CreateColomnSQL(
            MetaTable table,
            MetaDataMember member)
        {
            StringBuilder sqlText = new StringBuilder();

            sqlText.AppendFormat("{0} {1} ", member.MappedName, FilterDBType(member.DbType));

            if (member.IsPrimaryKey)
            {
                sqlText.AppendFormat("IDENTITY(1,1) CONSTRAINT PK_{0} PRIMARY KEY CLUSTERED ", table.TableName);
            }

            // TODO: Foreign key associations

            if (!member.CanBeNull)
            {
                sqlText.Append("NOT NULL");
            }

            return sqlText.ToString();
        }
예제 #24
0
		public override MetaDataMember GetDataMember(MemberInfo mi)
		{
			if(mi == null)
				throw Error.ArgumentNull("mi");
			MetaDataMember mm = null;
			if(this.dataMemberMap.TryGetValue(new MetaPosition(mi), out mm))
			{
				return mm;
			}
			else
			{
				// DON'T look to see if we are trying to get a member from an inherited type.
				// The calling code should know to look in the inherited type.
				if(mi.DeclaringType.IsInterface)
				{
					throw Error.MappingOfInterfacesMemberIsNotSupported(mi.DeclaringType.Name, mi.Name);
				}
				else
				{ //the member is not mapped in the base class
					throw Error.UnmappedClassMember(mi.DeclaringType.Name, mi.Name);
				}
			}
		}
 /// <summary>
 /// Provides the parameter type for a given data member
 /// </summary>
 /// <param name="objectToUpsert"></param>
 /// <param name="dataMember"></param>
 /// <param name="update"></param>
 /// <returns></returns>
 protected virtual ParameterType GetParameterType(object objectToUpsert, MetaDataMember dataMember, bool update)
 {
     var memberInfo = dataMember.Member;
     // the deal with columns is:
     // PK only:  explicit for INSERT, criterion for UPDATE
     // PK+GEN:   implicit/explicit for INSERT, criterion for UPDATE
     // GEN only: implicit for both
     // -:        explicit for both
     //
     // explicit is input,
     // implicit is output, 
     // criterion is input PK
     ParameterType type;
     if (dataMember.IsPrimaryKey)
     {
         if (update)
             type = ParameterType.InputPK;
         else
         {
             if (dataMember.IsDbGenerated)
             {
                 if (IsSpecified(objectToUpsert, memberInfo))
                     type = ParameterType.Input;
                 else
                     type = ParameterType.Output;
             }
             else
                 type = ParameterType.Input;
         }
     }
     else
     {
         if (dataMember.IsDbGenerated)
             type = ParameterType.Output;
         else
             type = ParameterType.Input;
     }
     return type;
 }
예제 #26
0
 internal abstract bool IsMemberPendingGeneration(MetaDataMember keyMember);
 private static Type GetMemberType(MetaDataMember member) {
     Type type = member.Type;
     if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(EntitySet<>)) {
         return type.GetGenericArguments()[0];
     }
     else {
         return type;
     }
 }
예제 #28
0
 internal SqlMember Member(SqlExpression expr, MetaDataMember member) {
     return new SqlMember(member.Type, this.Default(member), expr, member.Member);
 }
예제 #29
0
		private void GenerateAssignValue(MetaDataMember mm, LocalBuilder locInstance, SqlExpression expr, LocalBuilder locStoreInMember)
		{
			MemberInfo m = mm.StorageMember != null ? mm.StorageMember : mm.Member;
			if(!IsAssignable(m))
			{
				throw Error.CannotAssignToMember(m.Name);
			}
			Type memberType = TypeSystem.GetMemberType(m);

			Label labExit = gen.DefineLabel();

			bool hasSideEffect = this.HasSideEffect(expr);

			if(locStoreInMember != null && !hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			this.GenerateExpressionForType(expr, memberType, mm.DeclaringType.IsEntity ? locInstance : null);
			LocalBuilder locValue = gen.DeclareLocal(memberType);

			gen.Emit(OpCodes.Stloc, locValue);

			if(locStoreInMember != null && hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			this.GenerateLoadForMemberAccess(locInstance);
			gen.Emit(OpCodes.Ldloc, locValue);
			this.GenerateStoreMember(m);

			gen.MarkLabel(labExit);
		}
예제 #30
0
 private bool IsDbGeneratedKeyProjectionOnly(Expression projection, MetaDataMember keyMember) {
     NewArrayExpression array = projection as NewArrayExpression;
     if (array != null && array.Expressions.Count == 1) {
         Expression exp = array.Expressions[0];
         while (exp.NodeType == ExpressionType.Convert || exp.NodeType == ExpressionType.ConvertChecked) {
             exp = ((UnaryExpression)exp).Operand;
         }
         MemberExpression mex = exp as MemberExpression;
         if (mex != null && mex.Member == keyMember.Member) {
             return true;
         }
     }
     return false;
 }
 private void InitSpecialMember(MetaDataMember mm) {
     // Can only have one auto gen member that is also an identity member,
     // except if that member is a computed column (since they are implicitly auto gen)
     if (mm.IsDbGenerated && mm.IsPrimaryKey && string.IsNullOrEmpty(mm.Expression)) {
         if (this.dbGeneratedIdentity != null)
             throw Error.TwoMembersMarkedAsPrimaryKeyAndDBGenerated(mm.Member, this.dbGeneratedIdentity.Member);
         this.dbGeneratedIdentity = mm;
     }
     if (mm.IsPrimaryKey && !MappingSystem.IsSupportedIdentityType(mm.Type))
     {
         throw Error.IdentityClrTypeNotSupported(mm.DeclaringType, mm.Name, mm.Type);
     }
     if (mm.IsVersion) {
         if (this.version != null)
             throw Error.TwoMembersMarkedAsRowVersion(mm.Member, this.version.Member);
         this.version = mm;
     }
     if (mm.IsDiscriminator) {
         if (this.discriminator!=null)
             throw Error.TwoMembersMarkedAsInheritanceDiscriminator(mm.Member, this.discriminator.Member);
         this.discriminator = mm;
     }
 }
예제 #32
0
 private void InitOther() {
     if (this.otherType == null) {
         Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;
         this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot);
         System.Diagnostics.Debug.Assert(this.otherType.IsEntity);
         this.otherKey = (assocMap.OtherKey != null)
             ? MakeKeys(this.otherType, this.assocMap.OtherKey)
             : this.otherType.IdentityMembers;
         this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
         foreach (MetaDataMember omm in this.otherType.DataMembers) {
             if (omm.IsAssociation && omm != this.thisMember && omm.MappedName == this.thisMember.MappedName) {
                 this.otherMember = omm;
                 break;
             }
         }
     }
 }
예제 #33
0
        internal ProviderType Default(MetaDataMember member) {
            if(member == null) 
                throw Error.ArgumentNull("member");

            if (member.DbType != null) {
                return this.typeProvider.Parse(member.DbType);
            }
            else {
                return this.typeProvider.From(member.Type);
            }
        }
예제 #34
0
		private static string GetDbType(MetaDataMember mm)
		{
			string dbType = mm.DbType;

			if(dbType != null) return dbType;
			StringBuilder sb = new StringBuilder();

			Type type = mm.Type;
			bool isNullable = mm.CanBeNull;
			if(type.IsValueType && IsNullable(type))
			{
				type = type.GetGenericArguments()[0];
			}

			if(mm.IsVersion)
			{
				sb.Append("Timestamp");
			}
			else
			{
				if(mm.IsPrimaryKey && mm.IsDbGenerated)
				{
					switch(Type.GetTypeCode(type))
					{
						case TypeCode.Byte:
							sb.Append("TinyInt");
							break;
						case TypeCode.SByte:
						case TypeCode.Int16:
							sb.Append("SmallInt");
							break;
						case TypeCode.Int32:
						case TypeCode.UInt16:
							sb.Append("Int");
							break;
						case TypeCode.Int64:
						case TypeCode.UInt32:
							sb.Append("BigInt");
							break;
						case TypeCode.UInt64:
						case TypeCode.Decimal:
							sb.Append("Decimal(20)");
							break;
						case TypeCode.Object:
							if(type == typeof(Guid))
							{
								sb.Append("UniqueIdentifier");
							}
							else
							{
								throw Error.CouldNotDetermineDbGeneratedSqlType(type);
							}
							break;
					}
				}
				else
				{
					switch(Type.GetTypeCode(type))
					{
						case TypeCode.Boolean:
							sb.Append("Bit");
							break;
						case TypeCode.Byte:
							sb.Append("TinyInt");
							break;
						case TypeCode.SByte:
						case TypeCode.Int16:
							sb.Append("SmallInt");
							break;
						case TypeCode.Int32:
						case TypeCode.UInt16:
							sb.Append("Int");
							break;
						case TypeCode.Int64:
						case TypeCode.UInt32:
							sb.Append("BigInt");
							break;
						case TypeCode.UInt64:
							sb.Append("Decimal(20)");
							break;
						case TypeCode.Decimal:
							sb.Append("Decimal(29, 4)");
							break;
						case TypeCode.Double:
							sb.Append("Float");
							break;
						case TypeCode.Single:
							sb.Append("Real");
							break;
						case TypeCode.Char:
							sb.Append("NChar(1)");
							break;
						case TypeCode.String:
							sb.Append("NVarChar(4000)");
							break;
						case TypeCode.DateTime:
							sb.Append("DateTime");
							break;
						case TypeCode.Object:
							if(type == typeof(Guid))
							{
								sb.Append("UniqueIdentifier");
							}
							else if(type == typeof(byte[]))
							{
								sb.Append("VarBinary(8000)");
							}
							else if(type == typeof(char[]))
							{
								sb.Append("NVarChar(4000)");
							}
							else if(type == typeof(DateTimeOffset))
							{
								sb.Append("DateTimeOffset");
							}
							else if(type == typeof(TimeSpan))
							{
								sb.Append("Time");
							}
							else
							{
								throw Error.CouldNotDetermineSqlType(type);
							}
							break;
					}
				}
			}

			if(!isNullable)
			{
				sb.Append(" NOT NULL");
			}

			if(mm.IsPrimaryKey && mm.IsDbGenerated)
			{
				if(type == typeof(Guid))
				{
					sb.Append(" DEFAULT NEWID()");
				}
				else
				{
					sb.Append(" IDENTITY");
				}
			}

			return sb.ToString();
		}
예제 #35
0
		private void GenerateAssignDeferredReference(MetaDataMember mm, LocalBuilder locInstance, SqlExpression expr, LocalBuilder locStoreInMember)
		{
			MemberInfo m = mm.StorageMember != null ? mm.StorageMember : mm.Member;
			Type memberType = TypeSystem.GetMemberType(m);
			Diagnostics.Debug.Assert(
									 memberType.IsGenericType &&
									 (memberType.GetGenericTypeDefinition() == typeof(EntityRef<>) ||
									  memberType.GetGenericTypeDefinition() == typeof(Link<>))
				);
			Label labExit = gen.DefineLabel();
			Type argType = typeof(IEnumerable<>).MakeGenericType(memberType.GetGenericArguments());

			bool hasSideEffect = this.HasSideEffect(expr);

			if(locStoreInMember != null && !hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			Type eType = this.GenerateDeferredSource(expr, locInstance);
			if(!argType.IsAssignableFrom(eType))
			{
				throw Error.CouldNotConvert(argType, eType);
			}

			LocalBuilder locSource = gen.DeclareLocal(eType);
			gen.Emit(OpCodes.Stloc, locSource);

			if(locStoreInMember != null && hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			this.GenerateLoadForMemberAccess(locInstance);
			gen.Emit(OpCodes.Ldloc, locSource);
			ConstructorInfo ci = memberType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { argType }, null);
			Diagnostics.Debug.Assert(ci != null);
			gen.Emit(OpCodes.Newobj, ci);
			this.GenerateStoreMember(m);

			gen.MarkLabel(labExit);
		}
예제 #36
0
		private void GenerateAssignEntitySet(MetaDataMember mm, LocalBuilder locInstance, SqlExpression expr, LocalBuilder locStoreInMember)
		{
			MemberInfo m = mm.StorageMember != null ? mm.StorageMember : mm.Member;
			Type memberType = TypeSystem.GetMemberType(m);
			Diagnostics.Debug.Assert(memberType.IsGenericType && memberType.GetGenericTypeDefinition() == typeof(EntitySet<>));
			Label labExit = gen.DefineLabel();
			Type argType = typeof(IEnumerable<>).MakeGenericType(memberType.GetGenericArguments());

			bool hasSideEffect = this.HasSideEffect(expr);

			if(locStoreInMember != null && !hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			Type eType = this.Generate(expr, mm.DeclaringType.IsEntity ? locInstance : null);
			Diagnostics.Debug.Assert(argType.IsAssignableFrom(eType));
			LocalBuilder locSource = gen.DeclareLocal(eType);
			gen.Emit(OpCodes.Stloc, locSource);

			if(locStoreInMember != null && hasSideEffect)
			{
				gen.Emit(OpCodes.Ldloc, locStoreInMember);
				this.GenerateConstInt(0);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brtrue, labExit);
			}

			// if member is directly writeable, check for null entityset
			if(m is FieldInfo || (m is PropertyInfo && ((PropertyInfo)m).CanWrite))
			{
				Label labFetch = gen.DefineLabel();
				this.GenerateLoadForMemberAccess(locInstance);
				this.GenerateLoadMember(m);
				gen.Emit(OpCodes.Ldnull);
				gen.Emit(OpCodes.Ceq);
				gen.Emit(OpCodes.Brfalse, labFetch);

				// create new entity set
				this.GenerateLoadForMemberAccess(locInstance);
				ConstructorInfo ci = memberType.GetConstructor(System.Type.EmptyTypes);
				Diagnostics.Debug.Assert(ci != null);
				gen.Emit(OpCodes.Newobj, ci);
				this.GenerateStoreMember(m);

				gen.MarkLabel(labFetch);
			}

			// set the source
			this.GenerateLoadForMemberAccess(locInstance);
			this.GenerateLoadMember(m);
			gen.Emit(OpCodes.Ldloc, locSource);
			MethodInfo miAssign = memberType.GetMethod("Assign", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { argType }, null);
			Diagnostics.Debug.Assert(miAssign != null);
			gen.Emit(GetMethodCallOpCode(miAssign), miAssign);

			gen.MarkLabel(labExit);
		}
예제 #37
0
 private SqlExpression GetIdentityExpression(MetaDataMember id, bool isOutputFromInsert) {
     if (isOutputFromInsert) {
         return new SqlVariable(id.Type, sql.Default(id), "@id", this.dominatingExpression);
     }
     else {
         ProviderType sqlType = sql.Default(id);
         if (!IsLegalIdentityType(sqlType.GetClosestRuntimeType())) {                    
             throw Error.InvalidDbGeneratedType(sqlType.ToQueryString());
         }
         if ((this.converterStrategy & ConverterStrategy.CanUseScopeIdentity) != 0) {
             return new SqlVariable(typeof(decimal), typeProvider.From(typeof(decimal)), "SCOPE_IDENTITY()", this.dominatingExpression);
         }
         else {
             return new SqlVariable(typeof(decimal), typeProvider.From(typeof(decimal)), "@@IDENTITY", this.dominatingExpression);
         }
     }
 }
예제 #38
0
		private void GenerateMemberAssignment(MetaDataMember mm, LocalBuilder locInstance, SqlExpression expr, LocalBuilder locStoreInMember)
		{
			MemberInfo m = mm.StorageMember != null ? mm.StorageMember : mm.Member;
			Type memberType = TypeSystem.GetMemberType(m);

			// check for deferrable member & deferred source expression
			if(IsDeferrableExpression(expr) &&
			   (this.compiler.Services.Context.LoadOptions == null ||
				!this.compiler.Services.Context.LoadOptions.IsPreloaded(mm.Member))
				)
			{
				// we can only defer deferrable members 
				if(mm.IsDeferred)
				{
					// determine at runtime if we are allowed to defer load 
					gen.Emit(OpCodes.Ldarg_0);
					Type orbType = typeof(ObjectMaterializer<>).MakeGenericType(this.compiler.DataReaderType);
					PropertyInfo piCanDeferLoad = orbType.GetProperty("CanDeferLoad");
					Diagnostics.Debug.Assert(piCanDeferLoad != null);
					MethodInfo miCanDeferLoad = piCanDeferLoad.GetGetMethod();
					gen.Emit(GetMethodCallOpCode(miCanDeferLoad), miCanDeferLoad);

					// if we can't defer load then jump over the code that does the defer loading
					Label labEndDeferLoad = gen.DefineLabel();
					gen.Emit(OpCodes.Brfalse, labEndDeferLoad);

					// execute the defer load operation
					if(memberType.IsGenericType)
					{
						Type genType = memberType.GetGenericTypeDefinition();
						if(genType == typeof(EntitySet<>))
						{
							this.GenerateAssignDeferredEntitySet(mm, locInstance, expr, locStoreInMember);
						}
						else if(genType == typeof(EntityRef<>) || genType == typeof(Link<>))
						{
							this.GenerateAssignDeferredReference(mm, locInstance, expr, locStoreInMember);
						}
						else
						{
							throw Error.DeferredMemberWrongType();
						}
					}
					else
					{
						throw Error.DeferredMemberWrongType();
					}
					gen.MarkLabel(labEndDeferLoad);
				}
				else
				{
					// behavior for non-deferred members w/ deferrable expressions is to load nothing
				}
			}
			else if(memberType.IsGenericType && memberType.GetGenericTypeDefinition() == typeof(EntitySet<>))
			{
				this.GenerateAssignEntitySet(mm, locInstance, expr, locStoreInMember);
			}
			else
			{
				this.GenerateAssignValue(mm, locInstance, expr, locStoreInMember);
			}
		}