在多对多关系中,确保一个实体仅与另一个实体绑定

时间:2016-04-06 18:30:14

标签: c# entity-framework linq

这是一个令人费解的问题,但我不能完全理解我的想法。

我有三个表TableATableBTableABBridge。我需要检索TableABBridge中的所有值,其中来自TableB的记录仅绑定到TableA的单个记录。

基本上,我有一个工具允许用户编辑TableA中值的特定属性。但是,TableB也具有相同的属性,需要与TableA中的实体的属性保持同步。因此,如果我更新TableA中的值,则需要更新链接到特定实体的TableB中的所有值,但仅限TableB中的实体仅链接到一个实体来自TableA

所以例如

表A

|   ID   |   Prop   |
|-------------------|
|       1|         1|
|       2|         3|
|       3|         3|
|-------------------|

表B

|   ID   |   Prop   |
|-------------------|
|       1|         1|
|       2|         1|
|       3|         3|
|       4|         1|
|-------------------|

TableABBridge

|   AId   |   BId   |   
|-------------------|
|        1|        1|
|        1|        2|
|        1|        4|
|        2|        3|
|        3|        3|
|-------------------|

在上面的示例中,我只能将TableA中的ID 1的属性编辑为TableB的{​​{1}}的值1,2和4只与ID的{​​{1}} 1相关联。但是,我无法为ID 2或3编辑属性,因为它们共享TableA中的公共实体。

基本上,使用Linq,我需要弄清楚如何通过查询ID来获取我允许编辑的TableB个ID列表。

实现此目的的SQL是:

TableA

和反向(也需要)

TableABBridge

2 个答案:

答案 0 :(得分:0)

我相信一个可能的解决方案是:

var bridges = context.TableABBridge.Select(n => new
{
    n.AId,
    n.BId
}).Distinct()
.GroupBy(n => n.BId, n => n.AId).Where(n => n.Count() > 1)
.Select(n=>n.Key);

var uneditable = context.TableABBridge.Where(n => bridges.Contains(n.BId)).Select(n => n.AId);

var editable = context.TableABBridge.Select(n => new
{
    n.AId,
    n.BId
}).Distinct()
.GroupBy(n => n.BId, n => n.AId).Where(n => n.Count() == 1)
.Select(n => n.FirstOrDefault().Value);

答案 1 :(得分:0)

LINQ-ish方法是:

var diffs = from b in context.Bs
            where b.ABs.Count() == 1
            let a = b.ABs.FistOrDefault().A
            where a.Prop != b.Prop
            select new { b, ValueA = a.Prop };

foreach(var diff in diffs)
{
    diff.b.Prop = diff.ValueA;
}

context.Bs where b.ABs.Count() == 1为所有Bs提供1个联结记录,因此只有A。然后创建一个结构,其中B和A的值并排存储,因此很容易在循环中进行更新。

我说“LINQ-ish”,因为有时在LINQ中表达事物的自然方式与在SQL中更明显的方式不同(b.ABs.Count()GROUP BY)。它将为计数生成子查询,可能使其效率低于分组。但是也应该记住,LINQ group by并不总是被翻译成SQL GROUP BY