Entity Framework Code First: How can I determine the foreign key property used for a navigation property at runtime? -
i have entity framework code first dbcontext following entities configured. in example class bar child of class foo.
public class foo { public guid id { get; set; } public virtual icollection<bar> bars { get; set; } } public class bar { public guid id { get; set; } public guid fooid { get; set; } public virtual foo foo { get; set; } }
now know internally, entity framework understands relationship between foo , bar defined foreign key bar.fooid. i'd somehow extract relationship @ runtime using expressions. i'd implement method behaves follows:
var context = new foobardbcontext(); var bar = context.set<bar>().first(); // want method return bar.fooid when passed expression b => b.foo object result = myservice.getforeignkeyvalue(bar, b => b.foo);
now in simplistic example know bar.fooid , done. point i'm writing class believe getforeignkeyvalue method specified above cleanest interface user.
is possible query dbcontext configuration determine property used foreign key navigation property? (assuming there one)
i able determine foreign key properties using getdependentproperties method of navigationproperty class.
here code used (more or less) needed:
object[] getforeignkeypropertyvalues<tentity, trelatedentity>(tentity entity, expression<func<tentity, trelatedentity>> navigationproperty) { if (entity == null) return new object[] { }; // find entity metadata in object context. // (assume have access dbcontext through property currentdbcontext.) var objectcontext = (currentdbcontext iobjectcontextadapter).objectcontext; var metadatanamespace = objectcontextadapter.gettype().namespace; var entityidentity = metadatanamespace + "." + typeof(tentity).name; // hack: seems work retrieve entitytype entity. var entitymetadata = objectcontext.metadataworkspace.getitem<entitytype>(entityidentity, dataspace.cspace); // todo: verify entity metadata found. // navigation property metadata parsing name navigation property expression. var navigationpropertyname = getpropertyname(navigationproperty); var navigationpropertymetadata = entitymetadata.navigationproperties.firstordefault(np => np.name == navigationpropertyname); // todo: (jmb) verify navigation property metadata found. // extract foreign key columns navigation property. var foreignkeypropertymetadatas = navigationpropertymetadata.getdependentproperties(); // create property getters each foreign key property. var foreignkeypropertygetters = foreignkeypropertymetadatas .select(propertymetadata => makepropertygetter<tentity>(propertymetadata.name)) .toarray(); // execute foreign key property getters foreign key property values specified entity. var foreignkeypropertyvalues = foreignkeypropertygetters .select(propertygetter => propertygetter(entity)) .toarray(); return foreignkeypropertyvalues; } static string getpropertyname<tentity, tproperty>(expression<func<tentity, tproperty>> navigationproperty) { var lambda = navigationproperty lambdaexpression; var member = lambda.body memberexpression; return member.member.name; } static func<tentity, object> makepropertygetter<tentity>(type entitytype, string propertyname) { var parameterexpression = expression.parameter(typeof(tentity), "entity"); var propertyexpression = expression.propertyorfield(parameterexpression, propertyname); var lambdaexpression = expression.lambda(propertyexpression, parameterexpression); var lambdafunction = lambdaexpression.compile(); return (func<tentity, object>)lambdafunction; }
Comments
Post a Comment