【问题标题】:Generic Custom Join Extension Method通用自定义连接扩展方法
【发布时间】:2016-10-21 13:22:48
【问题描述】:

假设我们有 2 个表,TableATableB,它们之间存在 PK-FK 关系,我已经写了一个 extension methodjoin 这两个表并获取数据。这种扩展方法非常具体,可以为这两张表完成工作。

需要做些什么来创建一个 GENERIC 扩展方法来连接任意两个表并投影数据?

我的代码:

TableA 的架构:

CREATE TABLE [dbo].[TableA](
    [Id_1] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [Address] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED 
(
    [Id_1] ASC
) 

TableB 的架构:

CREATE TABLE [dbo].[TableB](
    [Id_2] [int] IDENTITY(1,1) NOT NULL,
    [Name2] [nvarchar](max) NULL,
    [Address2] [nvarchar](max) NULL,
    [FK_Id] [int] NULL,
PRIMARY KEY CLUSTERED 
(
    [Id_2] ASC
)
ALTER TABLE [dbo].[TableB]  WITH CHECK ADD FOREIGN KEY([FK_Id])
REFERENCES [dbo].[TableA] ([Id_1])

C#代码:

public class ABDTO
   {
       public TableA A { get; set; }
       public TableB B { get; set; }
    }

public static class Helper
    {
        public static IEnumerable<ABDTO> Join(this IEnumerable<TableA> tableA,IEnumerable<TableB> tableB)
        {
           return tableA.Join(tableB,x => x.Id_1,y => y.FK_Id,
                                    (x, y) =>new ABDTO
                                         {
                                             A = x,
                                              B = y
                                          });
                }

public class Program
    {
        static void Main(string[] args)
        {
            Operation1();
            Console.ReadLine();
        }

        public static void Operation1()
        {
            using (var db = new SampleEntities())
            {
                var result = db.TableAs.Join(db.TableBs);

                foreach(var item in result)
                {
                    Console.WriteLine("{0}; {1} ||| {2} ; {3}", item.A.Id_1, item.A.Name, item.B.Id_2, item.B.Name2);
                }
            }
        }
    }

所以,Join() 是一个extension method,它接受TableATableB,在PK-FK 关系上加入它们并投射出选择器。

我怎样才能将generic 写成:

public static IEnumerable<T> Join(this IEnumerable<T> Ta, IEnumerable<T> Tb)
        {
            return Ta.Join(Tb, x => Ta.SomeColumn1, y => Tb.SomeColumn2,
                                (x, y) => Projection of columns);
        }

LINQExtension methods我不是很擅长,请帮忙。 任何指针也会有所帮助。

【问题讨论】:

  • 您是否尝试接受列名作为参数?如果您将 Func 委托作为“加入”方法的参数。从调用代码中,您可以提供要用于加入的列,因此无需在“加入”扩展中硬编码。
  • @SIva Gopal...我没听懂你的意思..你能解释一下吗?
  • 您似乎正在寻找一种自动发现“可连接”列的方法。问题是:任何自动化程序如何知道您想加入什么?仅按名称约定(同名)?
  • 扩展方法对Join 本身的改进如何?似乎您缺少连接条件参数和结果定义,但添加这些参数可以有效地为您提供与 Join 相同的语法,所以我不确定您要进行哪些改进。
  • 你真的不应该在内存中执行这个连接;您应该在数据库中执行此连接。

标签: c# linq generics join extension-methods


【解决方案1】:

我做了一些研发,并能够推断出解决方案。

public class ABDTO<T,U> 
    {
        public T A { get; set; }
        public U B { get; set; }
    }
    public static class Helper
    {
        public static IQueryable<ABDTO<T,U>> JoinEx<T,U,Key>(this IQueryable<T> tableA,IQueryable<U> tableB, Expression<Func<T, Key>> column1, Expression<Func<U, Key>> column2)
        {
            return tableA.Join(tableB, column1, column2, (y, z) => new ABDTO<T,U> {A= y, B=z });
        }
    }

JoinEx&lt;&gt;() 是一个通用的extension 方法,它接受TU 类型的2 个表,在2 列的基础上将它们连接起来,并将结果投影到一些常见的DTO 中。

如下调用:

using (var db = new SampleEntities())
            {
                var result=db.TableAs.JoinEx<TableA, TableB, int>(db.TableBs, x => x.Id_1, y => y.FK_Id);  
                foreach(var item in result)
                {               
                        Console.WriteLine("{0} \t {1}",item.A.Name,item.B.Name2);                                       
                }
            }

我了解可能存在性能限制,并且此类操作必须在 database 中作为 stored procedure 执行,但对此类通用内容有要求。

谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-10
    • 2014-10-12
    • 1970-01-01
    • 2019-06-26
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多