Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建IQueryable<;T>;在EF中使用基类进行扩展_C#_Entity Framework_Linq_Inheritance - Fatal编程技术网

C# 创建IQueryable<;T>;在EF中使用基类进行扩展

C# 创建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()) {

我试图在我的基类上创建可重用的搜索查询,这样我就不必为每个Dervive类重复相同的代码,但我无法让entity framework很好地发挥作用

我有三门课: CMEntityBase 碳硅钙石 CMSiteServer

Site和SiteServer都派生自具有公共属性(ID、名称等)的CMEntityBase

我想定义一些通用搜索: e、 g.GetByName

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);
}