如何使用实体框架 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,可能你所有的表都有int
PK 的身份。如果您也从未从这些表中删除位于其他行之间的分隔行,则可以使用 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 按行号进行内部连接的主要内容,如果未能解决你的问题,请参考以下文章