我有许多结构相同但命名约定不同的实体对象,例如 Products1、Products2、Products3(这是遗留数据库模式的一部分,我对此无能为力)。
就 CLR 而言,这些类具有不同的类型,不幸的是,由于设计代码是自动生成的,我无法在这些人身上添加一个接口来显示共性。所以,我的问题是:有没有办法按名称检索实体对象?
在对这些对象应用基本相同的逻辑时,我基本上想避免切换/案例业务。
我有许多结构相同但命名约定不同的实体对象,例如 Products1、Products2、Products3(这是遗留数据库模式的一部分,我对此无能为力)。
就 CLR 而言,这些类具有不同的类型,不幸的是,由于设计代码是自动生成的,我无法在这些人身上添加一个接口来显示共性。所以,我的问题是:有没有办法按名称检索实体对象?
在对这些对象应用基本相同的逻辑时,我基本上想避免切换/案例业务。
您可以构建一个表达式树来查询有问题的一个或多个对象:
public T GetSingleObject<T>(int someValue) {
MyEntities db = new MyEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));
var param = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, "WhateverPropertyYourComparing"),
Expression.Constant(someValue)),
param);
return result.SingleOrDefault(lambda);
}
或者如果你想要一个对象的集合
public IEnumerable<T> GetResultCollection<T>(int someValue) {
MyEntities db = new MyEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));
var param = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, "WhateverPropertyYourComparing"),
Expression.Constant(someValue)),
param);
return result.Where(lambda);
}
当然,如果您想要的查询很长,这可能会失控,您应该考虑使用部分类添加必要的接口,正如 Justin Morgan 建议的那样。
请注意,此方法假定您的 ObjectSet 集合与您的对象同名,加上一个“s”,即“Invoice”到“Invoices”。如果不是这种情况,即“Person”到“People”,那么您可以使用 System.Data.Entity.Design.PluralizationServices.PluralizationService 来获取正确的名称
由于 EF4 类是部分类,因此您实际上可以扩展它们并使它们实现您选择的接口,所有这些都在一个单独的文件中。
另一种方法是使用dynamic
- 只需根据实体的类型实例化实体。
dynamic myEntity= Activator.CreateInstance(Type.GetType("EntityTypeHere")));
myEntity.CommonProperty = "Foo";
这里最大的缺点是你在编译时失去了所有类型安全——任何你只会在运行时发现的问题,而且它比静态类型的方法慢。
根据我们讨论的类的数量以及您需要的灵活性,接口可能不是不可能的。我使用泛型做了类似的事情:
//WARNING: Partially-remembered code ahead...
interface IDuckEntity
{
int FeatherCount { get; set; }
}
public partial class Products1 : IDuckEntity { }
public partial class Products2 : IDuckEntity { }
public partial class Products3 : IDuckEntity { }
//in some other class:
void DoStuff<T>(T entity) where T : EntityObject, IDuckEntity
{
entity.FeatherCount = 500;
}
因此,基本上,您设置了一个单独的文件,在其中放置接口和一些小的部分类声明。然后,您将可以访问通用结构。我不知道你的确切情况是什么,但这对我来说就像一个魅力。