How to add property-level Attribute to map ColumnAttribute at runtime?
Asked Answered
P

1

0

From this question we have implemented the ColumnAttribute association with the corresponding property, but when Linq to SQL tries to map this property to a Column it doesn't work.

Our property and mapping code(from the other question):

    public System.Xml.Linq.XElement Name {
        get {
            return this.name;
        }
        set {
            this.OnNameChanging(value);
            this.SendPropertyChanging();
            this.name = value;
            this.SendPropertyChanged("Name");
            this.OnNameChanged();
        }
    }

        System.Data.Linq.Mapping.ColumnAttribute columnAttribute = new System.Data.Linq.Mapping.ColumnAttribute();
        columnAttribute.Name = "Name";
        columnAttribute.Storage = "name";
        columnAttribute.DbType = "Xml NOT NULL";
        columnAttribute.CanBeNull = false;
        columnAttribute.UpdateCheck = System.Data.Linq.Mapping.UpdateCheck.Never;

        PropertyOverridingTypeDescriptor propertyOverrideTypeDescriptor = new PropertyOverridingTypeDescriptor(TypeDescriptor.GetProvider(typeof(ClassToMap)).GetTypeDescriptor(typeof(ClassToMap)));
        PropertyDescriptor pd = TypeDescriptor.GetProperties(typeof(ClassToMap)).Cast<PropertyDescriptor>().ToArray().Where(prop => prop.Name == "Name").FirstOrDefault();

        PropertyDescriptor pd2 = TypeDescriptor.CreateProperty(
            typeof(ClassToMap).GetType(),
            pd, // base property descriptor to which we want to add attributes
            // The PropertyDescriptor which we'll get will just wrap that
            // base one returning attributes we need.
            columnAttribute
            // this method really can take as many attributes as you like, not just one
        );

        propertyOverrideTypeDescriptor.OverrideProperty(pd2);
        TypeDescriptor.AddProvider(new TypeDescriptorOverridingProvider(typeof(ClassToMap)), typeof(ClassToMap));

Any idea how to refresh the table mapping?

Prevaricator answered 18/6, 2013 at 8:31 Comment(1)
I've tried this other alternative #394187 but still not working.Prevaricator
T
0

Reflection does not utilize type descriptors. Your test probably passed because another attribute is added to a class in code.

There is a way to change LINQ to SQL classes mapping on the fly. The trick is to add a XML mapping file to resources and use it when you create a data context. When you load XML data into memory, you can modify mappings as your needs dictate. This solution was described in detail here: Linq to sql using dynamic tables

The code snippet:

foreach (XElement col in xe.Descendants().Where(e => e.Name.LocalName == "Column")) {
    XAttribute name = col.Attributes().FirstOrDefault(a => a.Name.LocalName == "Name" && a.Value == "CategoryName");
    if (name != null)
        name.Value = "Name";
}
Twentyfourmo answered 19/6, 2013 at 1:11 Comment(5)
The example shows how to change the name of a database or a table. I need to add a ColumnAttribute. I don't see how to do it with xml mapping. Any idea?Prevaricator
That example demonstrates a general approach. If you look at the XML file, you will see that column properties are defined this way: <Column Name="CategoryID" Member="CategoryID" Storage="_CategoryID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> Where a mapping to a database field is defined via the Name attribute.Twentyfourmo
I've added Name attribute and still not working. My property's name is Name. Am I forgetting something?Prevaricator
Is your code similar to mine? I have recently added it to the answer.Twentyfourmo
Is there any other method to obtain the xml besides SQLMetal? Is there any other way to do the mapping without the xml with the same DataContext instance?Prevaricator

© 2022 - 2024 — McMap. All rights reserved.