如何在 MCV 中合并两个实体框架查询

Posted

技术标签:

【中文标题】如何在 MCV 中合并两个实体框架查询【英文标题】:How to Merge two Entity framework queries into on in MCV 【发布时间】:2021-07-26 15:49:42 【问题描述】:

我是公司的新人,他们聘请我为他们的 WPF 应用程序制作 MCV 版本。 我们使用实体框架来获取数据。 这是困境: 我有很多表可以同时提取到一个查询中。 我这样做:

 ... context.Citizens.Expand("person,person/passport") ...

expand 方法有效,但对添加的大约 15 个表有限制。可悲的是,我达到了极限,需要更多。 因此 WPF 应用程序解决此问题的方法是将先前的查询放入 DataServiceCollection 并在其上使用 .Load<T> 方法。我理解它的方式,它采用任何 EF 数据模型并添加缺少的字段并在任何地方填充数据。 (有点像超级合并)。

MVC 不支持这个神奇的功能,所以我需要帮助来做一些完全一样的东西。

示例: .Load 方法之前的表:

 Citizen  id, name, personId 
    Person  id, LoginInfo, PassportId 
    Passport  id, RealName, passportNumber etc etc 

.Load方法后的DataServiceCollection:

 Citizen id, name, personId, LoginInfo, PassportId, RealName, passportNumber etc etc

有谁知道我如何做到这一点?我希望对List<T> 进行扩展,这样它就可以做到。但任何事情都会有所帮助。

顺便说一句:我不需要DataServiceCollection<T>的内容更新,只需要数据合并功能。

编辑:

“合并”这个词似乎有些混乱......所以让我解释一下:

WPF 应用程序执行以下操作:

var expandString =
            "Person"
            + ",Person/foobar"
            + ",Person/foobar/bar"
            + ",Person/foobar/foofoofoobar"
            + ",Person/foobar/foofoofoobar/Type"
            + ",Foo1"
            + ",Foo1/foofoo"
            + ",Foo2"
            + ",Foo2/foofoo"
            + ",Foo3"
            + ",Foo3/foofoo"
            + ",Foo4"
            + ",Foo4/foofoo"
            + ",Foo5"
            + ",Foo5/foofoobar"
            + ",Foo5/foofoobar/bar";

IQueryable<Citizen> citizensQuery = 
    from cit in context.Citizens.Expand(expandString)
    where cit.Person.boobar.bar.barfoo.fuuId == _fuuId
    select cit;

var result = new DataServiceCollection<Citizen>(citizensQuery, 
    TrackingMode.None);

然后当你想在“结果”中添加更多额外的表格时,你只需使用 .Load 方法:

var moreExpandStrings = 
      "Citizenfoo"
    + ",foo6"
    + ",foo7"
    + ",foo8"
    + ",foo9"
    + ",foo10"
    + ",foo11";

result.Load(
    context.Citizens.Expand(moreExpandStrings)
    .Where(x => x.Person.boobar.bar.barfoo.fuuId == _fuuId
));

这个result.Load&lt;T&gt;() 方法采用 T 并将额外的变量添加到 EF 模型中,并从数据库中填充数据。 这就是我在 List 扩展方法中寻找的东西。如果需要,可以是繁重的代码。

【问题讨论】:

内存不足了吗?检查任务管理器。 我找到了解决该问题的解决方案。我只是为使用相同模型的每个调用创建一个新的 ContextContainer (ctx) 实例。在我的情况下,Citizen 已经创建并填充了一次数据,并且任何后续尝试将数据填充到其中,都会返回另一个查询。当我每次使用 Citizen 时使用不同的 ctx 实例时,我都会获得所有数据我想要,然后当我需要来自另一个查询的东西时,c# 可以很容易地使用 LINQ 来迭代这两个数据列表。它不干净,但它可以做什么.. 【参考方案1】:

如果您只是在寻找数据合并功能,您可以通过应用 Linq 来使用 AddRange() 方法。 here's a solution posted before

【讨论】:

【参考方案2】:

这看起来更像是 JOIN 而不是 MERGE。 Expand 的 EF 等效项是 Include。如果您只是想从您的问题构建投影并且您的实体和导航属性已正确配置,您可以在没有 INCLUDE 的情况下进行简单的 LINQ 投影(如果未配置关系,您可以使用 JOIN)。 Citizen 将拥有 Person 导航属性,而 Person 将拥有 Passport 导航:

var CitizenInfoList = context.Citizens
   .Where(x => x.Foo == "Bar")
   .Select(x => new myModel 
       id = x.Id,
       name = x.Name,
       LoginInfo = x.Person.LoginInfo,
       PassportId = x.Person.PassportId,
       RealName = x.Person.Passport.RealName ,
       PassportNumber = x.Person.Passport.PassportNumber 
   )
   .ToList();

仅转储实体:

var CitizenInfoList = context.Citizens
   .Include(p => p.Person.Select(c => c.Passport))
   .ToList();

另一个选项是数据库视图或存储过程。

【讨论】:

在阅读了更多关于 web + EF 的文档之后,你在这里的建议听起来不错.. 我会尝试一下,看看我是否能理解它.. 遗憾的是它没有成功。一旦我查询了 Citizens 模型,任何后续查询都将返回该结果而忽略其他查询请求。 DataServiceQuery 对象上不存在 .Include 子句。

以上是关于如何在 MCV 中合并两个实体框架查询的主要内容,如果未能解决你的问题,请参考以下文章

当我不知道记录是不是存在时,如何使用实体框架进行合并?

如何在没有实体的学说查询中合并连接表

如何动态构建实体框架查询?

在 Clojure 中,如何合并两个地图向量?

如何在原始查询中使用实体框架事务?

实体框架合并选项未跟踪不良性能