【问题标题】:Setting up an EF application's structure设置 EF 应用程序的结构
【发布时间】:2011-08-05 20:49:35
【问题描述】:

我正在使用 POCO 开发原型 EF 应用程序。主要作为对框架的介绍,我想知道一种以良好结构设置应用程序的好方法。稍后我打算将 WCF 纳入其中。

我所做的如下:

1) 我创建了一个 edmx 文件,但代码生成属性设置为 None 并生成了我的数据库架构,

2) 我创建的 POCO 看起来都像:

public class Person
{
    public Person()
    { 
    }

    public Person(string firstName, string lastName)
    {        

        FirstName = firstName;
        LastName = lastName;
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

3) 我创建了一个上下文

public class PocoContext : ObjectContext, IPocoContext
{
    private IObjectSet<Person> persons;

    public PocoContext() : base("name=PocoContainer", "PocoContainer")
    {
        ContextOptions.LazyLoadingEnabled = true;
        persons= CreateObjectSet<Person>();
    }

    public IObjectSet<Person> Persons
    {
        get
        {
            return persons;
        }
    }

    public int Save()
    {
        return base.SaveChanges();
    }
}

界面如下:

public interface IPocoContext
{
    IObjectSet<Person> Persons { get; }

    int Save();
}

4) 最后我创建了一个存储库,实现了一个接口:

public class PersonRepository : IEntityRepository<Person>
{
    private IPocoContext context;

    public PersonRepository()
    {
        context = new PocoContext();
    }

    public PersonRepository(IPocoContext context)
    {
        this.context = context;
    }

    // other methods from IEntityRepository<T>
}

public interface IEntityRepository<T>
{   
    void Add(T entity);
    List<T> GetAll();
    T GetById(int id);
    void Delete(T entity);

}

现在,当我开始玩这个时,这个设计要求我每次想要获取或改变一些数据时都要实例化一个存储库,如下所示:

using (var context = new PocoContext())
{   
    PersonRepository prep = new PersonRepository();

    List<Person> pers = prep.GetAll();
}

另一方面,在派生上下文中实例化每个存储库也感觉不太好,因为可能会实例化我可能根本不需要的对象。

关于如何使这个设计听起来不错的任何提示?我应该这样吗?这样做时我应该添加或避免什么?

【问题讨论】:

  • 是什么样的应用程序。 Web 服务、WPF 应用程序,还有什么?
  • 在这种状态下它只是一个控制台应用程序,因为它只是一个最低限度的原型。
  • 我问的原因是你如何处理你的上下文很大程度上受应用程序类型的影响。例如,在 wpf 应用程序中每个表单有一个上下文,在 Web 应用程序中每个 http 请求有一个上下文,在 Web 服务中每个方法调用有一个上下文,这是很常见的。
  • 本练习的最终目标是了解 EF 和 WCF,因此在我正确设置后,我会将其重构为以 WCF 为中心的应用程序。

标签: c# .net entity-framework architecture structure


【解决方案1】:

我不明白这部分:

using (var context = new PocoContext())
{   
    PersonRepository prep = new PersonRepository();

    List<Person> pers = prep.GetAll();
}

如果您调用存储库构造函数而不将上下文作为参数传递,为什么要在外部范围内创建上下文?使用多个上下文只会使事情变得更加困难。另外,如果您的外部块只会创建类的实例,那么为存储库创建接口并尝试隐藏它的意义何在?

你的方法正确吗?一般是的。您应该使用single context for logical operation(工作单元),如果您的存储库通过构造函数获取上下文,您需要为每个上下文创建一组新的存储库。这通常是通过依赖注入来实现的。

仅在派生上下文中实例化每个存储库并不 感觉也太好了,因为我可能会实例化对象 可能根本不需要。

这可以通过延迟初始化很容易解决:

private SomeRepositoryType _someRepository
public SomeRepositoryType SomeRepository
{
    get { _someRepository ?? (_someRepository = new SomeRepositoryType(context)) }
}

但我不会把它放到上下文中。我可能会在某些数据访问工厂中使用它,因为它应该在上下文之外,并且将单个工厂作为注入传递给使用多个存储库的类/方法更简单。

顺便说一句。 what value 你会从使用存储库中得到什么?

【讨论】:

  • 看了你的帖子后我想到了这一点,希望你能评论我要说的话。首先,这个项目的灵感主要来自一个教程,今天下午的午餐时间,我问自己同样的问题,这个问题的开始者所做的。存储库只是添加了一个额外的层,我称之为 AddObject(或其他)。也就是说,想想看,我实际上认为我现在没有从中受益......
【解决方案2】:

如果您使用 POCO 创建数据库模型,可以尝试 EF Code First 吗?恕我直言,使用 Code First 比在设计器中创建 EDMX 模型更清楚。

【讨论】:

  • 是的,但在这种情况下,我也可以挑选一些关于如何设置 edmx 的内容。
  • 真的,请遵循此建议并使用 Code First。首先,您没有理由与 EDMX 混为一谈。如果你真的想看看 edmx 的样子,可以选择从代码优先类生成它。
【解决方案3】:

通过提供每个请求的对象上下文,使用任何容器(如 Castle Windsor、AutoFac 等)使用依赖注入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多