创建有效的通用实体框架 linq 语句

Posted

技术标签:

【中文标题】创建有效的通用实体框架 linq 语句【英文标题】:Create valid generic Entity Framework linq statement 【发布时间】:2021-10-04 12:32:54 【问题描述】:

我有很多不同的表,代码级别(1 到 5,取决于表代表的区域)。您可以使用它们以不同的粒度级别进行搜索。所以我做了一个较小的例子。 EF 中的表在下方并添加到上下文 dbcontext。

public interface IDim1

    int Id  get; set; 
    string Dim1Code  get; set; 


public class Dim1 : IDim1

    public int Id  get; set; 
    public string Dim1Code  get; set; 


public interface IDim2 : IDim1

    string Dim2Code  get; set; 


public class Dim2 : IDim2

    public string Dim2Code  get; set; 


public interface IDim3 : IDim2

    string Dim3Code  get; set; 


public class Dim3 : Dim2, IDim3

    public string Dim3Code  get; set; 


public class House : Dim2

    public string House  get; set; 


public class Car : Dim1

    public string Car  get; set; 


public class Work : Dim3

    public string Employeer  get; set; 


public bool DimensionCodeExists<T>(string code) where T : Dim1

    var Querable = dbcontext.Set<T>().AsQuerable();

    if (typeof(Dim3).IsAssignableFrom(typeof(T)))
    
        //  They trouble is here
        return Querable.Cast<Dim3>().Any(o => o.Dim3Code == code || o.Dim2Code == code || o.Dim1Code == code);
    
    else if (typeof(Dim2).IsAssignableFrom(typeof(T)))
    
        // also here
        return Querable.Cast<Dim2>().Any(o => o.Dim2Code == code || o.Dim1Code == code);
    
    else
    
        // also here
        return Querable.Cast<Dim1>().Any(o => o.Dim1Code == code);
    

他们的麻烦就在这里,我真的需要告诉它有要搜索的代码,但我不能将它转换为 Dim3(或 Dim2 或 Dim1),因为那时 EF 会以 Expression 响应...“LINQ to Entities 仅支持转换实体数据模型原语类型” 如何转换它,以便我可以搜索我现在知道 T 具有的三个参数。

【问题讨论】:

【参考方案1】:

尝试使用反射:

private bool Dim3CodeExists<T>(string code) where T : Dim3

    return dbcontext.Set<T>().Any(o => o.Dim3Code == code || o.Dim2Code == code || o.Dim1Code == code);


private bool Dim2CodeExists<T>(string code) where T : Dim2

    return dbcontext.Set<T>().Any(o => o.Dim2Code == code || o.Dim1Code == code);


private bool Dim1CodeExists<T>(string code) where T : Dim1

    return dbcontext.Set<T>().Any(o => o.Dim1Code == code);


public bool DimensionCodeExists<T>(string code) where T : Dim1

    if (typeof(Dim3).IsAssignableFrom(typeof(T)))
    
        var openMethod = typeof(YourClass).GetMethod(nameof(Dim3CodeExists), BindingFlags.NonPublic | BindingFlags.Instance);
        var boundMethod = openMethod.MakeGenericMethod(typeof(T));
        return (bool)boundMethod.Invoke(this, new[]  code );
    
    
    if (typeof(Dim2).IsAssignableFrom(typeof(T)))
    
        var openMethod = typeof(YourClass).GetMethod(nameof(Dim2CodeExists), BindingFlags.NonPublic | BindingFlags.Instance);
        var boundMethod = openMethod.MakeGenericMethod(typeof(T));
        return (bool)boundMethod.Invoke(this, new[]  code );
    
    
    return Dim1CodeExists<T>(code);

【讨论】:

这行得通。有点难过,我需要反思来解决这个问题,但它确实有效。

以上是关于创建有效的通用实体框架 linq 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ to SQL 创建通用数据访问对象 (DAO) CRUD 方法

C# 动态Linq 建立模糊查询通用工具类

如何在实体框架模型中使用通用导航属性?

使用 Linq 表达式进行 C# 动态数据库过滤

使用Linq查找C#通用列表中的最新项目

为啥实体框架不能在 LINQ 语句中使用 ToString()?