sar*_*and 2 c# entity-framework objectcontext
我想创建一个工厂类来返回DbContext表名将作为字符串传递的对象.数据库中有100多个表,每个表都有不同的结构/模式.
我们的想法是通过tableName如string在将在EF返回对象,我们可以选择/更新这些记录的方法.我在一些文章中发现了这段代码,但是如何使用它却有些困惑:
public ObjectContext Context(EntityObject entity)
{
var relationshipManager = ((IEntityWithRelationships)entity).RelationshipManager;
var wrappedOwnerProperty = relationshipManager.GetType().GetProperty("WrappedOwner", BindingFlags.Instance | BindingFlags.NonPublic);
var wrappedOwner = wrappedOwnerProperty.GetValue(relationshipManager);
var contextProperty = wrappedOwner.GetType().GetProperty("Context");
return (ObjectContext)contextProperty.GetValue(wrappedOwner);
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是我需要的.还有什么我应该通过在EntityObject entity和我应该在哪里打发tableName?
如果有任何其他方法可以实现相同的目的,请告诉我.
一种简单的方法是使用DbContext.Set()方法,并根据字符串获取类型.
using (var db = new MyDbContext)
{
string tableName = "ApplicationUser";
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(t => t.Name == tableName);
if(type != null)
DbSet catContext = context.Set(type);
}
Run Code Online (Sandbox Code Playgroud)
然而,这有一个缺点,那就是这是一个非泛型的DbSet(即它DbSet不是a DbSet<T>).
获取Generic DbSet(允许linq功能)的方法是执行以下操作:
using (var db = new IdentityDbContext())
{
string tableName = "ApplicationUser";
var type = Assembly.GetExecutingAssembly()
.GetTypes().FirstOrDefault(t => t.Name == tableName);
var method = db.GetType().GetMethods()
.First(x => x.IsGenericMethod && x.Name == "Set");
MethodInfo generic = method.MakeGenericMethod(type);
var set = generic.Invoke(db, null);
}
Run Code Online (Sandbox Code Playgroud)
当然set在这里是一个对象,你必须以某种方式抛出它,这仍然是问题的一部分.
当它归结为它时,如果你不打算使用静态编译类型,你将不得不继续处理反射,特别是当你有通用类型来处理时(例如DbSet<T>,等等).您必须在某些时候将它们转换为静态类型以调用方法,或继续执行MethodInfo.Invoke.
另一个选择是使用动态,但你不能使用动态与c#扩展方法(没有强制转换为具体类型),所以你回到了没有Linq支持的同一条船上.
通过反射使用Linq是一个巨大的痛苦.
说实话,如果你有100个类,我只需咬紧牙关并编写硬编码类型,或使用代码生成器为你做CodeSmith.
| 归档时间: |
|
| 查看次数: |
4596 次 |
| 最近记录: |