实体框架 - 渴望模式 - 是否有更好的方法来过滤子关联?

时间:2015-10-08 12:06:22

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

重新制定问题:

  

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

上下文:

我有两个实体:

  

新闻
  + Id:int
  +日期:日期时间

     

NewsTranslation
  + NewsId:id(实体News.Id的外键)
  + LanguageCode:char(2)
  +标题:nvarchar(255)
  +内容:nvarchar(2000)

一个新闻可以包含 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)

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

1 个答案:

答案 0 :(得分:0)

我有两种方式可以看到;您可以使用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();它没有给你任何东西。