【问题标题】:Entity Framework - Eager mode - Is there a better way to filter child associations?实体框架 - 渴望模式 - 是否有更好的方法来过滤子关联?
【发布时间】:2015-10-08 12:06:22
【问题描述】:

问题的重新表述:

如何让代理解决部分加载的关节而不重新加载所有子关联?

上下文:

我有 2 个实体:

新闻
+ ID:整数
+ 日期:日期时间

新闻翻译
+ NewsId:id(实体 News.Id 的外键)
+ 语言代码:char(2)
+ 标题:nvarchar(255)
+ 内容:nvarchar(2000)

一个News可以有多个NewsTranslation(每个LanguageCode一个)

例如,这是数据库中的数据:

News {
 Id: 1,
 Date: "01/01/2015"
 Translations : [
    { NewsId: 1, LanguageCode: "en", Title: "Title", Contents: "English contents" },
    { NewsId: 1, LanguageCode: "fr", Title: "Titre", Contents: "French contents" }
 ]
}

我想加载新闻实体,但只加载当前语言翻译(例如英语“en”)。

我的代码:

News entity     = null;
var serializer  = new System.Web.Script.Serialization.JavaScriptSerializer();

using(var context = new MyContext()) 
{
    // Disabling lazyloading (see why at the bottom of the code)
    context.Configuration.LazyLoadingEnabled = false;

    // Load News with inner join NewsTranslation to retrieve 
    // only english language "en" 
    entity = (from news in context.News
               select new {
                   News = news,
                   NewsTranslation = from trans in news.NewsTranslation
                                     where trans.NewsId == news.Id
                                     && trans.LanguageCode == "en"
                                     select trans
               }).First()
}


//
// Serialize traverse all properties and associations.
//
// WITHOUT above "context.Configuration.LazyLoadingEnabled = false;" it would
// lazy load all associations NewsTranslation. Additionaly, the Context is closed so
// an exception is thrown
//
serializer.Serialize(entity)

这段代码可以正常工作,但我很害怕这样做......

在不禁用 LazyLoading 配置的情况下有更好的方法吗?


更新:

基于 Brian Mains 的建议:

翻译第一法:

News entity     = null;
var serializer  = new System.Web.Script.Serialization.JavaScriptSerializer();

using(var context = new MyContext()) 
{
    entity = (from trans in context.NewsTranslation
               where trans.LanguageCode == "en"
               select trans.News).First();
}


//
// The proxy try to lazy load News.NewsTransation association,
// so an exception is thrown beacause the Context is closed
// 
//
serializer.Serialize(entity)

同样的问题,如何让代理解决部分加载的关节?

【问题讨论】:

  • 当然:不要直接序列化实体/数据模型类。改用专用的“视图模型”或“域模型”......此外,该查询似乎从数据库中提取多个项目只是为了选择客户端的第一个项目。

标签: c# asp.net-mvc entity-framework linq


【解决方案1】:

嗯,我可以看到两种方式;您可以使用 let 关键字查询当前翻译(在 sql 中呈现子查询)。查看另一个 SO 示例:Using the "let" kewword in a LINQ Query with EF 4.3

或者,先查询翻译,包含新闻,然后构建模型:

var data = from trans in news.NewsTranslation.Include("News")
                                     where trans.LanguageCode == "en"
                                     select trans;

数据变量包含 NewsTranslation 对象,带有预加载的 News 属性;如果您想要的只是新闻,您可以将查询更改为:

var data = from trans in news.NewsTranslation
                                     where trans.LanguageCode == "en"
                                     select trans.News;

我不确定这会产生什么样的 LINQ,是否是简单的连接;您始终可以加入新闻实体并直接选择它,而不是使用新闻对象。

编辑:如果您只想要第一个对象,只需:

var results = (from trans in context.NewsTranslation
               where trans.LanguageCode == "en"
               select trans.News).First();

不要使用ToList(),也不要使用Select();它什么也得不到。

【讨论】:

  • 谢谢。我已经更新了我的问题。我只是测试了先查询翻译。我面临同样的问题:检索 News.NewsTranslation 时,代理尝试延迟加载完整的关联。我正在尝试使用 let 关键字的第二种方法...
  • 已编辑。只需在查询中使用 First() ;这应该会得到相同的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-01
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多