使用泛型的 LINQ 联接

LINQ join using Generics

提问人:Sridhar 提问时间:12/23/2012 最后编辑:Udara KasunSridhar 更新时间:10/8/2020 访问量:2300

问:

我正在尝试在泛型中编写 LINQ 联接查询,但在识别外键时遇到问题。PFB 代码。

我想识别表 U 中存在的外键,我可以将其用于比较操作。谢谢

var _tab = (from tblT in context.GetTable<T>()
            join tblU in context.GetTable<U>()
            on pk equals fk 
            select tblT).GetEnumerator();
C# .NET 泛型 LINQ-to-SQL

评论

9赞 Mahdi Tahsildari 12/23/2012
问题不明确
0赞 Mark Byers 12/23/2012
你在用什么?LINQ to SQL?实体框架?
0赞 Sridhar 12/23/2012
@mahditahsildari:清楚吗?StackOverflow 新手,在格式化方面遇到问题... :(
0赞 Gert Arnold 10/8/2020
您的问题描述是“在识别外键时遇到问题”。这还不清楚。

答:

6赞 Gary.S 12/23/2012 #1

您提到要“标识表 U 中存在的外键”。虽然你可以通过反思和某种约定来做到这一点,但这似乎是一个脆弱的解决方案。我建议您通过委托提供主键/外键关系。

基本上,联接使用委托来检索主键和外键,LINQ 提供程序将其转换为联接子句。连接的每一端的签名基本相同,在您的示例中为:和 。请务必注意,联接两端的密钥类型必须相同。Expression<Func<T, TKey>>Expression<Func<U, TKey>>

无论使用什么方法来调用此方法,都应要求传入这些委托。它可能看起来像这样:

public class Query
{
    public IEnumerable<T> GetData<T, U, TKey>(Expression<Func<T, TKey>> tKey, Expression<Func<U, TKey>> uKey)
    {
        Context context = new Context();
        // using the extension method as the query expression had trouble figuring out the types
        var data = context.GetTable<T>().Join(context.GetTable<U>(), tKey, uKey, (tblT, tblU) => tblT);            

        return data;
    }
}

调用它看起来像这样:

var data = query.GetData<Person, Order, int>(person => person.Id, order => order.Orderer.Id);

评论

0赞 Jegan 7/10/2020
我正在寻找的绝妙解决方案,谢谢。
0赞 Udara Kasun 10/8/2020 #2

我改进了@Gary.S的答案。在这里,我改进了查询选择器以及如何在此处使用 where close。我认为这将对你有所帮助。

这是我更新的通用方法

注意:AppDbContext 是我的 dbContext

public class MyGenMetClass
{
    public async Task<IEnumerable<TResult>> FetchJonBy<TOuter, TInner, TKey, TResult>(Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, bool>> wherOuter, Expression<Func<TInner, bool>> wherInner, Expression<Func<TOuter, TInner, TResult>> resultSelector) where TOuter : class where TInner : class where TResult : class
     {
       try
       {
           using (AppDbContext db = new AppDbContext())
           {
                var data = await db.Set<TOuter>().Where(wherOuter).Join(db.Set<TInner>().Where(wherInner), outerKeySelector, innerKeySelector, resultSelector).ToListAsync();
                    return data;
            }
       }catch (Exception ex){
            return null;
       }
   }
}

而我的模型是这样的。

供应商模型

public class SupplierModel
{
        [Key]
        public int SupplierId { get; set; }
        public string Name { get; set; }
        public int CategoryId { get; set; }
}

供应商Catgory

public class SupplierCatgory
{
       [Key]
       public int CategoryId { get; set; }
       public string Category { get; set; }        
       public Boolean IsActive { get; set; } = true;  
}

供应商视图模型

public class SupplierViewModel
{       
        public int SupplierId { get; set; }
        public string Name { get; set; }
        public int CategoryId { get; set; }
        public string Category { get; set; }
}

在这里,我加入了 SupplierModel 和 SupplierCatgory返回 SupplierViewModel

你可以这样称呼

var result =await new MyGenMetClass().FetchJonBy<SupplierModel,SupplierCatgory,int, SupplierViewModel>(s=> s.CategoryId,c=>c.CategoryId ,m=>m.IsAcvtive==true,c=>c.IsActive==true, (s, y) => new SupplierViewModel() { Name=s.Name,Category=y.Category} );

评论

1赞 Gert Arnold 10/8/2020
常规方法有什么问题?(即使是原来的答案也没有增加太多)。你的方法不必要地复杂,尤其是这些,其中的子句比它们有帮助更令人讨厌。Join
0赞 Udara Kasun 10/8/2020
我同意这有点复杂。但您可以使用它返回 Viewmodel(自定义模型),而不是将单个模型作为列表返回。此外,您还可以使用 where 线索来过滤数据。
0赞 Gert Arnold 10/8/2020
此外,您还可以使用 where 线索来过滤数据 -- 是的,但你不能使用它们,这涵盖了 99% 的联接用例。如果需要,只有常规也会返回任何视图模型。Join
0赞 Gert Arnold 10/8/2020
我什至没有提到返回 as 会阻止此方法的使用者对结果进行组合。(也适用于原件)。IQueryableIEnumerable