public AttributedColumnMetaDataMember(MemberInfo member, ColumnAttribute attribute, MetaType declaringType)
            : base(member, declaringType, attribute)
        {
            columnAttribute = attribute;
            if (columnAttribute.Name == null)
                columnAttribute.Name = memberInfo.Name;
        }
Beispiel #2
0
 internal PropertyData(PropertyInfo pi)
 {
     this.PropertyInfo = pi;
     ColumnAttribute = ReflectionHelper.GetAttributes<ColumnAttribute>(pi, true).FirstOrDefault();
     FqlFieldName = GetLinqFieldName();
     IsLinqIdentity = GetIsLinqIdentity();
 }
 public AttributedColumnMetaDataMember(MemberInfo member, ColumnAttribute attribute, MetaType declaringType)
     : base(member, declaringType, member.DeclaringType.GetSingleMember(attribute.Storage))
 {
     columnAttribute = attribute;
     if (columnAttribute.Name == null)
         columnAttribute.Name = memberInfo.Name;
 }
		internal AttributedMetaDataMember(AttributedMetaType metaType, MemberInfo mi, int ordinal)
		{
			this.declaringType = mi.DeclaringType;
			this.metaType = metaType;
			this.member = mi;
			this.ordinal = ordinal;
			this.type = TypeSystem.GetMemberType(mi);
			this.isNullableType = TypeSystem.IsNullableType(this.type);
			this.attrColumn = (ColumnAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnAttribute));
			this.attrAssoc = (AssociationAttribute)Attribute.GetCustomAttribute(mi, typeof(AssociationAttribute));
			this.attr = (this.attrColumn != null) ? (DataAttribute)this.attrColumn : (DataAttribute)this.attrAssoc;
			if(this.attr != null && this.attr.Storage != null)
			{
				MemberInfo[] mis = mi.DeclaringType.GetMember(this.attr.Storage, BindingFlags.Instance | BindingFlags.NonPublic);
				if(mis == null || mis.Length != 1)
				{
					throw Error.BadStorageProperty(this.attr.Storage, mi.DeclaringType, mi.Name);
				}
				this.storageMember = mis[0];
			}
			Type storageType = this.storageMember != null ? TypeSystem.GetMemberType(this.storageMember) : this.type;
			this.isDeferred = IsDeferredType(storageType);
			if(attrColumn != null && attrColumn.IsDbGenerated && attrColumn.IsPrimaryKey)
			{
				// auto-gen identities must be synced on insert
				if((attrColumn.AutoSync != AutoSync.Default) && (attrColumn.AutoSync != AutoSync.OnInsert))
				{
					throw Error.IncorrectAutoSyncSpecification(mi.Name);
				}
			}
		}
Beispiel #5
0
 public void Ctor()
 {
     var c = new ColumnAttribute();
     Assert.AreEqual(AutoSync.Default,   c.AutoSync);
     Assert.AreEqual(true,               c.CanBeNull);
     Assert.AreEqual(null,               c.DbType);
     Assert.AreEqual(null,               c.Expression);
     Assert.AreEqual(false,              c.IsDbGenerated);
     Assert.AreEqual(false,              c.IsDiscriminator);
     Assert.AreEqual(false,              c.IsVersion);
     Assert.AreEqual(UpdateCheck.Always, c.UpdateCheck);
     Assert.AreEqual(false,              c.IsPrimaryKey);
     Assert.AreEqual(null,               c.Name);
     Assert.AreEqual(null,               c.Storage);
     Assert.AreEqual(c.GetType(),        c.TypeId);
 }
        private static void CopyAttributeToMapping(ColumnAttribute attribute, IColumnMapping mapping)
        {
            if (attribute == null) return;

            if (attribute.IsDbGenerated) mapping.DbGenerated();
            if (attribute.IsPrimaryKey) mapping.PrimaryKey();
            if (attribute.IsVersion) mapping.Version();
            if (!attribute.CanBeNull) mapping.NotNull();

            if (!string.IsNullOrEmpty(attribute.DbType)) mapping.DbType(attribute.DbType);
            if (!string.IsNullOrEmpty(attribute.Name)) mapping.Named(attribute.Name);
            if (!string.IsNullOrEmpty(attribute.Expression)) mapping.Expression(attribute.Expression);
            if (!string.IsNullOrEmpty(attribute.Storage)) mapping.Storage(attribute.Storage);

            mapping.AutoSync(attribute.AutoSync);
            mapping.UpdateCheck(attribute.UpdateCheck);

            //TODO: Discriminator
        }
        /// <summary>
        /// Writes property accessor
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="property"></param>
        /// <param name="relatedAssociations"></param>
        /// <param name="context"></param>
        protected virtual void WriteClassPropertyAccessors(CodeWriter writer, Column property, IEnumerable<Association> relatedAssociations, GenerationContext context)
        {
            //generate [Column(...)] attribute
            var column = NewAttributeDefinition<ColumnAttribute>();
            column["Storage"] = property.Storage;
            column["Name"] = property.Name;
            column["DbType"] = property.DbType;
            // be smart: we only write attributes when they differ from the default values
            var columnAttribute = new ColumnAttribute();
            if (property.IsPrimaryKey != columnAttribute.IsPrimaryKey)
                column["IsPrimaryKey"] = property.IsPrimaryKey;
            if (property.IsDbGenerated != columnAttribute.IsDbGenerated)
                column["IsDbGenerated"] = property.IsDbGenerated;
            if (property.AutoSync != DbLinq.Schema.Dbml.AutoSync.Default)
                column["AutoSync"] = new EnumFullname("AutoSync", property.AutoSync);
            if (property.CanBeNull != columnAttribute.CanBeNull)
                column["CanBeNull"] = property.CanBeNull;
            if (property.Expression != null)
                column["Expression"] = property.Expression;

            var specifications = property.AccessModifierSpecified
                                     ? GetSpecificationDefinition(property.AccessModifier)
                                     : SpecificationDefinition.Public;
            if (property.ModifierSpecified)
                specifications |= GetSpecificationDefinition(property.Modifier);

            //using (WriteAttributes(writer, context.Parameters.MemberExposedAttributes))
            using (WriteAttributes(writer, GetAttributeNames(context, context.Parameters.MemberAttributes)))
            using (writer.WriteAttribute(NewAttributeDefinition<DebuggerNonUserCodeAttribute>()))
            using (writer.WriteAttribute(column))
            using (writer.WriteProperty(specifications, property.Member, GetTypeOrExtendedType(writer, property)))
            {
                // on auto storage, we're just lazy
                if (property.Storage == null)
                    writer.WriteAutomaticPropertyGetSet();
                else
                {
                    using (writer.WritePropertyGet())
                    {
                        writer.WriteLine(writer.GetReturnStatement(writer.GetVariableExpression(property.Storage)));
                    }
                    using (writer.WritePropertySet())
                    {
                        WriteClassPropertyAccessorSet(writer, property, relatedAssociations, context);
                    }
                }
            }
        }
        protected CodeTypeDeclaration GenerateTableClass(Table table, Database database)
        {
            var _class = new CodeTypeDeclaration() {
                IsClass         = true, 
                IsPartial       = true, 
                Name            = table.Type.Name, 
                TypeAttributes  = TypeAttributes.Public,
                CustomAttributes = {
                    new CodeAttributeDeclaration("Table", 
                        new CodeAttributeArgument("Name", new CodePrimitiveExpression(table.Name))),
                },
            };

            WriteCustomTypes(_class, table);

            var havePrimaryKeys = table.Type.Columns.Any(c => c.IsPrimaryKey);
            if (havePrimaryKeys)
            {
                GenerateINotifyPropertyChanging(_class);
                GenerateINotifyPropertyChanged(_class);
            }

            // Implement Constructor
            var constructor = new CodeConstructor() { Attributes = MemberAttributes.Public };
            // children are EntitySet
            foreach (var child in GetClassChildren(table))
            {
                // if the association has a storage, we use it. Otherwise, we use the property name
                var entitySetMember = GetStorageFieldName(child);
                constructor.Statements.Add(
                    new CodeAssignStatement(
                        new CodeVariableReferenceExpression(entitySetMember),
                        new CodeObjectCreateExpression(
                            new CodeTypeReference("EntitySet", new CodeTypeReference(child.Type)),
                            new CodeDelegateCreateExpression(
                                new CodeTypeReference("Action", new CodeTypeReference(child.Type)),
                                thisReference, child.Member + "_Attach"),
                            new CodeDelegateCreateExpression(
                                new CodeTypeReference("Action", new CodeTypeReference(child.Type)),
                                thisReference, child.Member + "_Detach"))));
            }
            constructor.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(thisReference, "OnCreated")));
            _class.Members.Add(constructor);

            if (Context.Parameters.GenerateEqualsHash)
            {
                GenerateEntityGetHashCodeAndEquals(_class, table);
            }

            GenerateExtensibilityDeclarations(_class, table);

            // todo: add these when the actually get called
            //partial void OnLoaded();
            //partial void OnValidate(System.Data.Linq.ChangeAction action);

            // columns
            foreach (Column column in table.Type.Columns)
            {
                var relatedAssociations = from a in table.Type.Associations
                                          where a.IsForeignKey && a.TheseKeys.Contains(column.Name)
                                          select a;

                var type = ToCodeTypeReference(column);
                var columnMember = column.Member ?? column.Name;

                var field = new CodeMemberField(type, GetStorageFieldName(column));
                _class.Members.Add(field);
                var fieldReference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name);

                var onChanging  = GetChangingMethodName(columnMember);
                var onChanged   = GetChangedMethodName(columnMember);

                var property = new CodeMemberProperty();
                property.Type = type;
                property.Name = columnMember;
                property.Attributes = MemberAttributes.Public | MemberAttributes.Final;

                var defAttrValues = new ColumnAttribute();
                var args = new List<CodeAttributeArgument>() {
                    new CodeAttributeArgument("Storage", new CodePrimitiveExpression(GetStorageFieldName(column))),
                    new CodeAttributeArgument("Name", new CodePrimitiveExpression(column.Name)),
                    new CodeAttributeArgument("DbType", new CodePrimitiveExpression(column.DbType)),
                };
                if (defAttrValues.IsPrimaryKey != column.IsPrimaryKey)
                    args.Add(new CodeAttributeArgument("IsPrimaryKey", new CodePrimitiveExpression(column.IsPrimaryKey)));
                if (defAttrValues.IsDbGenerated != column.IsDbGenerated)
                    args.Add(new CodeAttributeArgument("IsDbGenerated", new CodePrimitiveExpression(column.IsDbGenerated)));
                if (column.AutoSync != DbLinq.Schema.Dbml.AutoSync.Default)
                    args.Add(new CodeAttributeArgument("AutoSync", 
                        new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("AutoSync"), column.AutoSync.ToString())));
                if (defAttrValues.CanBeNull != column.CanBeNull)
                    args.Add(new CodeAttributeArgument("CanBeNull", new CodePrimitiveExpression(column.CanBeNull)));
                if (column.Expression != null)
                    args.Add(new CodeAttributeArgument("Expression", new CodePrimitiveExpression(column.Expression)));
                property.CustomAttributes.Add(
                    new CodeAttributeDeclaration("Column", args.ToArray()));
                property.CustomAttributes.Add(new CodeAttributeDeclaration("DebuggerNonUserCode"));

                property.GetStatements.Add(new CodeMethodReturnStatement(fieldReference));

                var whenUpdating = new List<CodeStatement>(
                    from assoc in relatedAssociations
                    select (CodeStatement) new CodeConditionStatement(
                        new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(GetStorageFieldName(assoc)),
                            "HasLoadedOrAssignedValue"),
                        new CodeThrowExceptionStatement(
                            new CodeObjectCreateExpression(typeof(System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException)))));
                whenUpdating.Add(
                        new CodeExpressionStatement(new CodeMethodInvokeExpression(thisReference, onChanging, new CodePropertySetValueReferenceExpression())));
                if (havePrimaryKeys)
                    whenUpdating.Add(
                            new CodeExpressionStatement(new CodeMethodInvokeExpression(thisReference, "SendPropertyChanging")));
                whenUpdating.Add(
                        new CodeAssignStatement(fieldReference, new CodePropertySetValueReferenceExpression()));
                if (havePrimaryKeys)
                    whenUpdating.Add(
                            new CodeExpressionStatement(new CodeMethodInvokeExpression(thisReference, "SendPropertyChanged", new CodePrimitiveExpression(property.Name))));
                whenUpdating.Add(
                        new CodeExpressionStatement(new CodeMethodInvokeExpression(thisReference, onChanged)));

                var fieldType = TypeLoader.Load(column.Type);
                // This is needed for VB.NET generation; 
                // int/string/etc. can use '<>' for comparison, but NOT arrays and other reference types.
                // arrays/etc. require the 'Is' operator, which is CodeBinaryOperatorType.IdentityEquality.
                // The VB IsNot operator is not exposed from CodeDom.
                // Thus, we need to special-case: if fieldType is a ref or nullable type,
                //  generate '(field Is value) = false'; otherwise, 
                //  generate '(field <> value)'
                CodeBinaryOperatorExpression condition = fieldType.IsClass || fieldType.IsNullable()
                    ? ValuesAreNotEqual_Ref(new CodeVariableReferenceExpression(field.Name), new CodePropertySetValueReferenceExpression())
                    : ValuesAreNotEqual(new CodeVariableReferenceExpression(field.Name), new CodePropertySetValueReferenceExpression());
                property.SetStatements.Add(new CodeConditionStatement(condition, whenUpdating.ToArray()));
                _class.Members.Add(property);
            }

            GenerateEntityChildren(_class, table, database);
            GenerateEntityChildrenAttachment(_class, table, database);
            GenerateEntityParents(_class, table, database);

            return _class;
        }
Beispiel #9
0
        /// <summary>
        /// Gets the length limit for a given field on a LINQ object ... or zero if not known
        /// </summary>
        /// <remarks>
        /// You can use the results from this method to dynamically 
        /// set the allowed length of an INPUT on your web page to
        /// exactly the same length as the length of the database column.  
        /// Change the database and the UI changes just by
        /// updating your DBML and recompiling.
        /// </remarks>
        public static int GetLengthLimit(ColumnAttribute ca)
        {
            if (ca == null)
            {
                return int.MaxValue;
            }

            int dblenint = 0;   // default value = we can't determine the length

            string dbtype = ca.DbType;

            if (dbtype.StartsWith("NChar") || dbtype.StartsWith("NVarChar"))
            {
                int index1 = dbtype.IndexOf("(");
                int index2 = dbtype.IndexOf(")");
                string dblen = dbtype.Substring(index1 + 1, index2 - index1 - 1);
                if (dblen == "MAX")
                {
                    return int.MaxValue;
                }
                int.TryParse(dblen, out dblenint);
            }

            return dblenint;
        }