Search code examples
linq-to-sqlreflectionattributesupdatecheck

Linq to SQL - Turn off UpdateCheck in code


I am wanting to turn off the UpdateCheck functionality for all members (except their primary keys). Now I was following the example below as guidance, however my MetaDataMembers of the table are still set to Always.

http://www.the-lazy-coder.com/2013/04/set-updatecheck-to-never.html

The above code snippet just gets you to change the attribute, however it seems to never get picked up, as I can debug the code when it is running and I see all the properties being set, so I am presuming that the attributes changing does not change the underlying object.

Now if I were to change approach and just get the MetaDataMembers directly from the RowType I notice they have the UpdateCheck property, however only a getter. So is there a way to (via reflection if needed) overwrite this property once it is set? Even after looking at decompiled source it is an abstract class and I cannot find any implementations to use for reference.

I am using SQLMetal to generate the Context files, so there is no designer tinkering available, and although some people will say that I should run some text editing macros to parse and change the attributes, it all sounds too long winded when I should just be able to go into the object in memory and tell it to ignore whatever it has been told previously.

SO! Is there a way to override the property in the entities? I have tried running the original code in that link in both constructor, after the objects created and just before I am about to do an update, however none of the changes seem to stick or at least propagate to where it matters, and there is hardly any material on how to do any of this progmatically.


Solution

  • After searching around the internet I found no nice way to do it, and although there is the link I mentioned originally it doesn't work as it works on the attributes which are partly right but in the case above they are working on the attributes which are not in memory and are just the decorations, anyway the code below seems to work but is not nice:

    public static void SetUpdateCheckStatus(this IDataContext dataContext, UpdateCheck updateCheckStatus)
            {
                var tables = dataContext.Mapping.GetTables();
                foreach (var table in tables)
                {
                    var dataMembers = table.RowType.DataMembers;
                    foreach (var dataMember in dataMembers)
                    {
                        if (!dataMember.IsPrimaryKey)
                        {
                            var dataMemberType = dataMember.GetType();
                            if (dataMemberType.Name == "AttributedMetaDataMember")
                            {
                                var underlyingAttributeField = dataMember.GetType().GetField("attrColumn", BindingFlags.Instance | BindingFlags.NonPublic);
                                if (underlyingAttributeField != null)
                                {
                                    var underlyingAttribute = underlyingAttributeField.GetValue(dataMember) as ColumnAttribute;
                                    if (underlyingAttribute != null)
                                    { underlyingAttribute.UpdateCheck = updateCheckStatus; }
                                }
                            }
                            else
                            {
                                var underlyingField = dataMember.Type.GetField("updateCheck", BindingFlags.Instance | BindingFlags.NonPublic);
                                if (underlyingField != null)
                                { underlyingField.SetValue(dataMember, updateCheckStatus); }
                            }
                        }
                    }
                }
            }
    

    The IDataContext is just a wrapper we put around a DataContext for mocking purposes, so feel free to change that to just DataContext. It is written extremely defensively as this way pulls back lots of members which do not have all the desired data so it has to filter them out and only work on the ones which do.