设置EF应用程序的结构

时间:2020-12-19 23:02:56

I'm working on a prototype EF application, using POCOs. Mainly as an introduction to the framework I'm wondering about a good way to set up the application in a nice structure. Later on I'm planning to incorporate WCF into it.

我正在使用POCOs开发EF原型应用程序。主要是作为框架的介绍,我想知道在一个好的结构中设置应用程序的一个好方法。稍后我打算将WCF合并到其中。

What I've done is the following:

我所做的是:

1) I created an edmx file, but with the Code Generation Property set to None and generated my database schema,

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

2) I created the POCOs which all look like:

2)我创造了POCOs,看起来都像:

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) I created a Context

我创建了一个上下文

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();
    }
}

The interface looks like this:

界面是这样的:

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

    int Save();
}

4) Lastly I created a repository, implementing an interface:

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);

}

Now, when I get on playing around with this, this design dictates me to instantiate a repository every time I want to fetch or mutate some data, like this:

现在,当我开始研究这个问题时,这个设计要求我每次都要实例化一个存储库,比如:

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

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

Somehow this just feels wrong and flawed, on the other hand, just instantiating every repository in the derived context doesn't feel too good either, because of potentially instantiating objects I might not need at all.

从某种程度上来说,这感觉是错误的和有缺陷的,另一方面,仅仅实例化派生上下文中的每个存储库也不太好,因为可能实例化我可能根本不需要的对象。

Any tips on how to make this design sound? Should I leave it this way? Any things I should add or avoid in general when doing this?

关于如何使这个设计听起来有什么建议吗?我应该这样走吗?在做这个的时候,我有什么需要补充或避免的吗?

3 个解决方案

#1


2  

I don't understand this part:

我不理解这部分:

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

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

Why are you creating the context in outer scope if you call repository constructor without passing the context as parameter? Using multiple contexts will make things only much harder. Also what is the point of making the interface for repository and trying to hide it if your outer block will just create instance of the class?

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

Is your approach correct? Generally yes. You should use single context for logical operation (unit of work) and if your repository gets context through constructor you need to create a new set of repositories for each context. This is usually achieved through dependency injection.

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

just instantiating every repository in the derived context doesn't feel too good either, because of potentially instantiating objects I might not need at all.

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

Well this can be solved pretty easily by lazy initialization:

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

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

But I would not put this into context itself. I would probably use this in some data access factory because it should be outside of the context and passing single factory as injection to classes / methods using multiple repositories is simpler.

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

Btw. what value will you get from using repository?

顺便说一句。您将从使用存储库中获得什么价值?

#2


1  

If you use POCO to create model of your database, maeby try EF Code First? IMHO using Code First is more clearly than creating EDMX model in designer.

如果您使用POCO创建数据库模型,请先使用maeby尝试EF代码?IMHO首先使用代码比在设计器中创建EDMX模型更清楚。

#3


0  

Use Dependency Injection using any container like Castle Windsor, AutoFac , etc by providing per request Object Context.

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

#1


2  

I don't understand this part:

我不理解这部分:

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

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

Why are you creating the context in outer scope if you call repository constructor without passing the context as parameter? Using multiple contexts will make things only much harder. Also what is the point of making the interface for repository and trying to hide it if your outer block will just create instance of the class?

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

Is your approach correct? Generally yes. You should use single context for logical operation (unit of work) and if your repository gets context through constructor you need to create a new set of repositories for each context. This is usually achieved through dependency injection.

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

just instantiating every repository in the derived context doesn't feel too good either, because of potentially instantiating objects I might not need at all.

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

Well this can be solved pretty easily by lazy initialization:

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

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

But I would not put this into context itself. I would probably use this in some data access factory because it should be outside of the context and passing single factory as injection to classes / methods using multiple repositories is simpler.

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

Btw. what value will you get from using repository?

顺便说一句。您将从使用存储库中获得什么价值?

#2


1  

If you use POCO to create model of your database, maeby try EF Code First? IMHO using Code First is more clearly than creating EDMX model in designer.

如果您使用POCO创建数据库模型,请先使用maeby尝试EF代码?IMHO首先使用代码比在设计器中创建EDMX模型更清楚。

#3


0  

Use Dependency Injection using any container like Castle Windsor, AutoFac , etc by providing per request Object Context.

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