我有一个通用的CRUD类来执行添加,删除,选择,创建我的实体对象。
其中一个 - 消息有两个派生类 - order_message和report_message。
我的问题是,在我的泛型类中,我需要一个objectset来执行crud操作,但是objectset不接受派生类类型,它只接受基类类型。
这是我收到的错误:
没有为指定的实体类型'CustomerWebPortal_Entities.Order_Message'定义EntitySet。如果'CustomerWebPortal_Entities.Order_Message'是派生类型,请改用基类型。
我尝试使用typeof(T).BaseType来替换T,并且原因不起作用。
我该如何纠正?
这是泛型类的概述:
public abstract class baseCrudDao<T> : ICrudDao<T> where T : class
{
private System.Data.Objects.ObjectContext _context;
private System.Data.Objects.ObjectSet<T> _entity;
public baseCrudDao()
{
_context = new CustomerWebPortalEntities();
_entity = _context.CreateObjectSet<T>(); <-- error at here, only accept base type
}
答案 0 :(得分:3)
好吧,我终于有机会按照建议编写原型。我认为像这样的东西会起作用,但我还没有测试过。现在可以针对IObjectSet<>
成员定义所有crud方法。
public class Crud<EntityType> where EntityType : class
{
private readonly ObjectContext Context;
private readonly IObjectSet<EntityType> Entities;
public Crud(ObjectContext context)
{
Context = context;
Type BaseType = GetBaseEntityType();
if (BaseType == typeof(EntityType))
{
Entities = Context.CreateObjectSet<EntityType>();
}
else
{
Entities = (IObjectSet<EntityType>)Activator.CreateInstance(typeof(ObjectSetProxy<,>).MakeGenericType(typeof(EntityType), BaseType), Context);
}
}
private static Type GetBaseEntityType()
{
//naive implementation that assumes the first class in the hierarchy derived from object is the "base" type used by EF
Type t = typeof(EntityType);
while (t.BaseType != typeof(Object))
{
t = t.BaseType;
}
return t;
}
}
internal class ObjectSetProxy<EntityType, BaseEntityType> : IObjectSet<EntityType>
where EntityType : BaseEntityType
where BaseEntityType : class
{
private readonly IObjectSet<BaseEntityType> Entities;
public ObjectSetProxy(ObjectContext context)
{
Entities = context.CreateObjectSet<BaseEntityType>();
}
public void AddObject(EntityType entity)
{
Entities.AddObject(entity);
}
//TODO: implement remaining proxy methods
public IEnumerator<EntityType> GetEnumerator()
{
return Entities.OfType<EntityType>().GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Type ElementType
{
get { return typeof(EntityType); }
}
public Expression Expression
{
get { return Entities.OfType<EntityType>().Expression; }
}
public IQueryProvider Provider
{
get { return Entities.Provider; }
}
}
答案 1 :(得分:0)
一种解决方法是使用两个泛型类型参数(在基类上),例如
public abstract class baseCrudDao<T, U> : ICrudDao<T> where U : class, T: U
{
...
public baseCrudDao()
{
_context = new CustomerWebPortalEntities();
_entity = _context.CreateObjectSet<U>(); <-- error at here, only accept base type
}
...
}
使用Message代替U.如果你有很多类型而不是所有类型都有继承关系,那么约束T:U将不起作用,你需要使用T:class约束。我还建议你创建另一个骨架基类,用于其他类型,如
public abstract class base2CrudDao<T> : baseCrudDao<T, T>
这样您就不必为没有继承关系的类指定U参数。