C# 创建IQueryable<;T>;在EF中使用基类进行扩展
我试图在我的基类上创建可重用的搜索查询,这样我就不必为每个Dervive类重复相同的代码,但我无法让entity framework很好地发挥作用 我有三门课: CMEntityBase 碳硅钙石 CMSiteServer Site和SiteServer都派生自具有公共属性(ID、名称等)的CMEntityBase 我想定义一些通用搜索: e、 g.GetByNameC# 创建IQueryable<;T>;在EF中使用基类进行扩展,c#,entity-framework,linq,inheritance,C#,Entity Framework,Linq,Inheritance,我试图在我的基类上创建可重用的搜索查询,这样我就不必为每个Dervive类重复相同的代码,但我无法让entity framework很好地发挥作用 我有三门课: CMEntityBase 碳硅钙石 CMSiteServer Site和SiteServer都派生自具有公共属性(ID、名称等)的CMEntityBase 我想定义一些通用搜索: e、 g.GetByName using (var db = new LNOSCMDataModel()) {
using (var db = new LNOSCMDataModel())
{
db.Configuration.LazyLoadingEnabled = false;
var servers = db.CMSiteServers.
AsNoTracking().
GetByName(id,Active).
ConvertToAPIVM().ToList();
}
我尝试了几种定义GetByName的方法:
基类:
public static IQueryable<CMEntityBase> GetByName(this IQueryable<CMEntityBase> Entities, string Name, bool Active = true)
{
return Entities.Where(ss => ss.Name == Name && ss.Active == Active || Active == false);//.Cast<IEntity>();
}
public static IQueryable GetByName(此IQueryable实体,字符串名称,bool Active=true)
{
返回Entities.Where(ss=>ss.Name==Name&&ss.Active==Active | | Active==false);/.Cast();
}
仿制药:
public static IQueryable<T> GetByName<T>(this IQueryable<CMEntityBase> Entities, string Name, bool Active = true) where T : CMEntityBase
{
return Entities.Where(ss => ss.Name == Name && ss.Active == Active || Active == false).Cast<T>();
}
公共静态IQueryable GetByName(此IQueryable实体,字符串名称,bool Active=true),其中T:CMEntityBase
{
返回Entities.Where(ss=>ss.Name==Name&&ss.Active==Active | | Active==false).Cast();
}
我尝试过将基类定义为接口,并在泛型中使用T:class,IEntity(interface)
-->这种方法来自:
最终,它们都返回错误:
LINQ to实体仅支持使用IEntity接口强制转换EDM基元或枚举类型
最后,我想在基类属性上定义一个查询,但输出子类。现在看来,我需要复制/粘贴每个派生类的方法。经过大量实验,解决方案是将基类创建为抽象类
public abstract class CMEntityBase
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public abstract decimal ID { get; set; }
[StringLength(50)]
public abstract string Name { get; set; }
....
}
在静态扩展类中定义我的扩展,这里的关键是使用。选择(e=>e as T)将其转换回子类
public static partial class CMEntityBaseExtensions
{
public static IQueryable<T> GetByName<T>(this IQueryable<T> Entities, string Name, bool Active = true) where T : CMEntityBase
{
return Entities.Where(ss => ss.Name == Name && ss.Active == Active || Active == false).
Select(e => e as T); // cast back to child!
}
}
事件使用我的“casting”函数转换为视图模型
var servers = servers1.
ConvertToAPIVM().ToList();
看起来是这样的:
public static partial class CMSiteServerExtensions
{
public static IQueryable<CMSiteServerAPIVM> ConvertToAPIVM(this IQueryable<CMSiteServer> Servers)
{
return Servers.Select(ss => new CMSiteServerAPIVM()
{
SiteServerID = ss.ID,
Name = ss.Name,
Description = ss.Description,
...
}
}
}
公共静态部分类CMSiteServerExtensions
{
公共静态iQuery可转换为PIVM(此iQuery可转换服务器)
{
返回服务器。选择(ss=>newcmsiteserverpivm()
{
SiteServerID=ss.ID,
Name=ss.Name,
Description=ss.Description,
...
}
}
}
而不是接受与所需类型不同的IQueryable
,并尝试强制转换它(如错误所示,不支持该类型)您只需接受查询已经存在的实际类型的IQueryable
,这样就不需要强制转换它。在这种情况下,它与在原始查询中使用泛型类型一样简单,而不是基类型:
public static IQueryable<T> GetByName<T>(this IQueryable<T> Entities, string Name, bool Active = true)
where T : CMEntityBase //or the interface that specifies the needed members
{
return Entities.Where(ss => ss.Name == Name && ss.Active == Active || Active == false);
}
public static IQueryable GetByName(此IQueryable实体,字符串名称,bool Active=true)
其中T:CMEntityBase//或指定所需成员的接口
{
返回实体。其中(ss=>ss.Name==Name&&ss.Active==Active | | Active==false);
}
我没有对你投反对票,但我怀疑你的粗体文本是否正确,因为查询已经是t类型的,因此不需要强制转换,因为它所做的一切就是将t转换为t。我需要再次回顾,我记得当时有一些问题,但时间已经足够长了,我不记得为什么有必要这样做,因为它本不应该这样做。
public static IQueryable<T> GetByName<T>(this IQueryable<T> Entities, string Name, bool Active = true)
where T : CMEntityBase //or the interface that specifies the needed members
{
return Entities.Where(ss => ss.Name == Name && ss.Active == Active || Active == false);
}