.net - How to I define/change the mappings for Linq To Sql in code -


i wish able change table class mapped @ run time, can’t if mappings defined attributes. therefore there way define mappings @ runtime in code.

(i rather not have maintain xml mapping files.)


say have 2 tables:

  • olddata
  • newdata

and wished query olddata , other times wished query newdata. want use same code build queries in both cases.


see "how map entity framework model table name dynamically"

in order make transparent, have jump through pretty crazy hoops, can done overriding meta*** classes own derived types.

this straightforward proxy/method interception library castle, assuming lowest common denominator here, it's long , boring ordeal of implementing every single meta method wrap original type, because can't derive directly of attribute mapping classes.

i'll try stick important overrides here; if don't see particular method/property in code below, means implementation literally one-liner wraps "inner" method/property , returns result. i've posted whole thing, one-line methods , all, on pastebin can cut/paste testing/experimentation.

the first thing need quick override declaration, looks this:

class tableoverride {     public tableoverride(type entitytype, string tablename)     {         if (entitytype == null)             throw new argumentnullexception("entitytype");         if (string.isnullorempty(tablename))             throw new argumentnullexception("tablename");         this.entitytype = entitytype;         this.tablename = tablename;     }      public type entitytype { get; private set; }     public string tablename { get; private set; } } 

now meta classes. starting lowest level, have implement metatype wrapper:

class overridemetatype : metatype {     private readonly metamodel model;     private readonly metatype innertype;     private readonly metatable overridetable;      public overridemetatype(metamodel model, metatype innertype,         metatable overridetable)     {         if (model == null)             throw new argumentnullexception("model");         if (innertype == null)             throw new argumentnullexception("innertype");         if (overridetable == null)             throw new argumentnullexception("overridetable");         this.model = model;         this.innertype = innertype;         this.overridetable = overridetable;     }      public override metamodel model     {         { return model; }     }      public override metatable table     {         { return overridetable; }     } } 

again, have implement 30 properties/methods this, i've excluded ones return innertype.xyz. still me? ok, next metatable:

class overridemetatable : metatable {     private readonly metamodel model;     private readonly metatable innertable;     private readonly string tablename;      public overridemetatable(metamodel model, metatable innertable,         string tablename)     {         if (model == null)             throw new argumentnullexception("model");         if (innertable == null)             throw new argumentnullexception("innertable");         if (string.isnullorempty(tablename))             throw new argumentnullexception("tablename");         this.model = model;         this.innertable = innertable;         this.tablename = tablename;     }      public override metamodel model     {         { return model; }     }      public override metatype rowtype     {         { return new overridemetatype(model, innertable.rowtype, this); }     }      public override string tablename     {         { return tablename; }     } } 

yup, boring. ok, next metamodel itself. here things little more interesting, start declaring overrides:

class overridemetamodel : metamodel {     private readonly mappingsource source;     private readonly metamodel innermodel;     private readonly list<tableoverride> tableoverrides = new          list<tableoverride>();      public overridemetamodel(mappingsource source, metamodel innermodel,         ienumerable<tableoverride> tableoverrides)     {         if (source == null)             throw new argumentnullexception("source");         if (innermodel == null)             throw new argumentnullexception("innermodel");         this.source = source;         this.innermodel = innermodel;         if (tableoverrides != null)             this.tableoverrides.addrange(tableoverrides);     }      public override type contexttype     {         { return innermodel.contexttype; }     }      public override string databasename     {         { return innermodel.databasename; }     }      public override metafunction getfunction(methodinfo method)     {         return innermodel.getfunction(method);     }      public override ienumerable<metafunction> getfunctions()     {         return innermodel.getfunctions();     }      public override metatype getmetatype(type type)     {         return wrap(innermodel.getmetatype(type));     }      public override metatable gettable(type rowtype)     {         return wrap(innermodel.gettable(rowtype));     }      public override ienumerable<metatable> gettables()     {         return innermodel.gettables().select(t => wrap(t));     }      private metatable wrap(metatable innertable)     {         tableoverride ovr = tableoverrides.firstordefault(o =>              o.entitytype == innertable.rowtype.type);         return (ovr != null) ?             new overridemetatable(this, innertable, ovr.tablename) :              innertable;     }      private metatype wrap(metatype innertype)     {         tableoverride ovr = tableoverrides.firstordefault(o =>             o.entitytype == innertype.type);         return (ovr != null) ?             new overridemetatype(this, innertype, wrap(innertype.table)) :             innertype;     }      public override mappingsource mappingsource     {         { return source; }     } } 

we're done! need mapping source:

class overridemappingsource : mappingsource {     private readonly mappingsource innersource;     private readonly list<tableoverride> tableoverrides = new         list<tableoverride>();      public overridemappingsource(mappingsource innersource)     {         if (innersource == null)             throw new argumentnullexception("innersource");         this.innersource = innersource;     }      protected override metamodel createmodel(type datacontexttype)     {         var innermodel = innersource.getmodel(datacontexttype);         return new overridemetamodel(this, innermodel, tableoverrides);     }      public void overridetable(type entitytype, string tablename)     {         tableoverrides.add(new tableoverride(entitytype, tablename));     } } 

now can start using (phew):

var realsource = new attributemappingsource(); var overridesource = new overridemappingsource(realsource); overridesource.overridetable(typeof(customer), "newcustomer"); string connection = properties.settings.default.myconnectionstring; using (mydatacontext context = new mydatacontext(connection, overridesource)) {     // work here } 

i've tested queries , insertions (insertonsubmit). it's possible, rather likely, i've missed in basic testing. oh, , work if 2 tables literally exactly same, column names , all.

it mess if table has associations (foreign keys), since you'd have override association names too, on both ends. i'll leave exercise reader, since thinking makes head hurt. you'd better off removing associations particular table, don't have deal headache.

have fun!


Comments

Popular posts from this blog

javascript - Enclosure Memory Copies -

php - Replacing tags in braces, even nested tags, with regex -