如何使用实体框架 6 按行号进行内部连接

Posted

技术标签:

【中文标题】如何使用实体框架 6 按行号进行内部连接【英文标题】:How to do an inner join by row number using Entity Framework 6 【发布时间】:2017-09-08 23:46:07 【问题描述】:

两个表:

表A有以下数据:

Type1 A
Type1 B
Type1 C
Type1 D

表B有以下数据:

Type2 X
Type2 Y
Type2 U
Type2 V

我想得到以下输出:

new  A, X 
new  B, Y 
new  C, U 
new  D, V 

这可能使用实体框架吗?我现在面临的问题是有 8 个不同的实体表,每个表代表一个类型。该应用程序有一个索引页面,我们希望在索引页面上显示每个表的 6 个项目。我们当然可以一个一个地做到这一点,但这会打到 DB 8 次,这可能效率不高。使用 EF 6 解决此类问题的正确方法是什么?

【问题讨论】:

【参考方案1】:

试试这个:

var AX = db.tableA 
.Join( 
tableB, 
foo1 => foo1.A, 
foo2 => foo2.X, 
(foo1, foo2) => new  foo1, foo2
.ToList()



var BY = db.tableA 
    .Join( 
    tableB, 
    foo1 => foo1.B, 
    foo2 => foo2.Y, 
    (foo1, foo2) => new  foo1, foo2
    .ToList()

  var CU = db.tableA 
    .Join( 
    tableB, 
    foo1 => foo1.C, 
    foo2 => foo2.U, 
    (foo1, foo2) => new  foo1, foo2
    .ToList()

  var DV = db.tableA 
    .Join( 
    tableB, 
    foo1 => foo1.D, 
    foo2 => foo2.V, 
    (foo1, foo2) => new  foo1, foo2
    .ToList()

【讨论】:

我认为这行不通。首先,每个 ToList() 都将被转换为一个 sql 查询,正如我在问题中所说的那样,这是我想要避免的。其次,没有 on 条件的 join 将被转换为完全交叉连接,这将是一个笛卡尔积,而不是我想要的。【参考方案2】:

如果你使用EF,可能你所有的表都有intPK 的身份。如果您也从未从这些表中删除位于其他行之间的分隔行,则可以使用 Id 列作为连接条件。您可以使用相同的方式将此示例简单地扩展到所需数量的表。

var tableA = from itemA in ctx.tableA
             let minId = ctx.tableA.Min(x => x.Id)
             select new  itemA, index = itemA.Id - minId ;

var tableB = from itemB in ctx.tableB 
             let minId = ctx.tableB.Min(x => x.Id)
             select new  itemB, index = itemB.Id - minId ;

var answer = (from itemAA in tableA
              join itemBB in tableB on itemAA.index equals itemBB.index
              select new  itemAA.itemA, itemBB.itemB).ToList().SelectMany(x => 
                  var result = new List<Tuple<Type1, Type2>>();
                  var props1 = x.itemA.GetType().GetProperties().ToList();
                  var props2 = x.itemB.GetType().GetProperties().ToList();
                  for(var i = 0; i < Math.Min(props1.Count, props2.Count); i++)                              
                       result.Add(new Tuple<Type1, Type2>((Type1)props1[i].GetValue(x.itemA), (Type2)props2[i].GetValue(x.itemB)));
                   return result;                                  
              ).ToList();

【讨论】:

以上是关于如何使用实体框架 6 按行号进行内部连接的主要内容,如果未能解决你的问题,请参考以下文章

使用Moq模拟实体框架6 ObjectResult

无法将 MySQL 连接用于实体框架 6

在实体框架中使用视图

如何使用实体框架连接三个表来获取所有数据

实体框架6-然后按First()进行排序所需的时间太长

如何使用 .Include 查询实体框架 6 强制外部联接