实体框架 - 加载子对象的策略

时间:2010-09-03 22:20:16

标签: .net entity-framework repository

我得到了以下2个实体:用户和帖子

简单版用户:

public virtual int Id { get; set; }
public virtual IList<Post> Posts { get; set; }

默认情况下不会加载帖子。

在某些情况下,我需要加载帖子(例如,我想计算该用户的帖子数量)。现在,我在UserRepository中添加了一个方法调用LoadPosts(用户用户):

_context.LoadProperty(user, "Posts");
  • 是否有更合理的地方放置该方法?
  • 我应该把它放在PostRepository中吗?类似于CountPosts(int userId)?
  • 我应该在LoadMethod上提供过载。示例:Load(bool loadPosts)

有没有办法,如果我写myUser.Posts.Count()帖子是自动加载而不是null?

4 个答案:

答案 0 :(得分:6)

您描述的场景称为延迟加载,EF4支持它。根据您的代码判断,您有POCO对象,并且由于您已将列表声明为virtual,因此EF可以创建代理以提供延迟加载功能。您可以使用一个设置来启用延迟加载:context.ContextOptions.LazyLoadingEnabled = true;。在这种情况下,无论何时访问已加载Posts的{​​{1}}属性,数据都将从数据库加载。

此处有更多信息,请参阅“延迟/延迟加载”部分: http://blogs.msdn.com/b/adonet/archive/2009/05/28/poco-in-the-entity-framework-part-2-complex-types-deferred-loading-and-explicit-loading.aspx

  

这之所以有效是因为   当我标记我的收藏属性   作为虚拟,这允许实体   提供代理实例的框架   对于我在运行时的POCO类型,它是   这个代理自动完成   延期装载。代理实例   基于派生自的类型   我自己的POCO实体类 - 所以全部   您提供的功能是   保存。从开发人员的角度来看   查看,这可以让你写   持久性无知的代码即使   延期加载可能是一个   要求。

简要介绍一下您的小问题列表:

  • 是否有更合理的地方放置该方法? - 如果您决定实施 为给定加载User的方法 用户自己,它在逻辑上属于 Posts
  • 我应该把它放在PostRepository中吗?像CountPosts(int userId)之类的东西 ? - 它可能属于 如果您加载,请UserRepository 与某个用户无关的帖子 (例如,全局关键字搜索 所有帖子)。
  • 我应该在LoadMethod上提供过载。示例:加载(布尔 loadPosts) - 是的,你可以这样做。 但是,使用EF,你只需要 关闭延迟加载。帖子会 与用户一起加载。

答案 1 :(得分:0)

如果您使用自定义数据提供程序,在这种情况下,我建议您使用CreateDataSource方法加载数据。

答案 2 :(得分:0)

您应该通过重载或添加新方法将其放在Repository中。 For More

如果您在存储库外调用_context.Load()而不是incorrect

答案 3 :(得分:0)

  
    

是否有更合理的地方放置该方法?

  

IMO,是的。除非你需要很多时间的帖子列表,否则我不会有这样的特定方法。我会 Eager Load 帖子 on demand 。 (更多关于此,见下文)

  
    

我应该把它放在PostRepository吗?

  

八九不离十。 LoadPosts(User user)是PostRepository特定的登录名,IMO。但是 - 它是一个非常特定的方法..这意味着,你或早到PostRepository将会非常忙于许多特定的方法。我们通常有一个通用的存储库,允许 Expressions 进来。这样,您就不需要创建许多特定的方法。您可以使用一种方法来排除表达式并检索各种请求。

例如。

IQueryable<Post> Find(Expression<Func<Post, bool>> predicate, 
                      string[] includeAssociations);

然后你可以用它来急切加载你需要的东西。

例如。获取特定用户的所有帖子。

var posts = _postRepostitory
    .Find(x => x.UserId = userId, new [] { "User" } )
    .ToList();

或另一方面,对于用户,请告诉我他们所有的帖子......

var user = _userRepository
    .Find(x => x.UserId = userId, new [] { "Posts" } )
    .ToList();

如果您需要Find方法中的代码方面的帮助,请问..但它非常简单。

这个想法是这样的(按顺序,这是非常的)

  • 表达式仅应用于Post实例内隐藏上下文中的postRespository实体。
  • 最后,对于每个需要的关联,最后为Include

没有什么是硬编码的。它们都是由编码器在调用Find方法时定义的。一种方法来统治它们。

注意:当然,我实际上有4 - 1没有参数..一直到我已经显示的那个,有4个args。

  
    

像CountPosts(int userId)?

  

(未经测试,pseduo代码......在我的脑海中思考)

var count = _postRepostiory
    .Find(x => x.UserId = userId, new [] { "Posts" })
    .Select(x => x.Posts).Count;
  
    

我应该在LoadMethod上提供过载。示例:加载(bool loadPosts)

  

不。现在不需要。

  
    

有没有办法,如果我写myUser.Posts.Count()帖子是自动加载而不是null?

  

是的,如果你按照我上面的建议。

var user = _userRepository
    .Find(x => x.UserId = userId, new [] { "Posts" })
    .SingleOrDefault();

var postCount = user == null || user.Posts == null ? 0 : user.Posts.Count;

疯狂地编程,padawan !!