c# - 您如何在 Web 应用程序中集中 Entity Framework 数据上下文?

标签 c# entity-framework entity-framework-4 repository datacontext

在我们的应用程序中,我们使用存储库模式从我们的数据存储介质中检索和保存数据。我们选择使用的媒介是 Entity Framework 4。这似乎是一种非常干净的做事方式,并且在 99% 的时间里都运行良好。

现在我们遇到了一个问题。我们有两个存储库,如下所示:

public class UserRepository : IUserRepository
{
    Entities dataContext = new Entities();

    public User GetUser(string username)
    {
        return dataContext.Users.SingleOrDefault(x => x.Username == username);
    }

    // ... more CRUD-style methods that are not relevant to this question.

    public void SaveChanges()
    {
        dataContext.SaveChanges();
    }
}

public RoleRepository : IRoleRepository
{
    Entities dataContext = new Entities();

    public Role GetRole(string name)
    {
        return dataContext.Roles.SingleOrDefault(x => x.Name == name);
    }

    // ... more CRUD-style methods that are not relevant to this question.

    public void SaveChanges()
    {
        dataContext.SaveChanges();
    }
}

用户和角色在 Entity Framework 模型中实际上是多对多的关系。有时我们想获取现有用户和现有角色并将两者相关联。通常,如果您像这样编写一个简短的示例代码片段,这会很有效:

Entities dataContext = new Entities();
Role roleToAdd = dataContext.Roles.Single(x => x.Name == "Admin");
User user = dataContext.Users.Single(x => x.Username == "Fred");
user.Roles.Add(roleToAdd);
dataContext.SaveChanges();

这很有效,因为两个实体都是从同一个 EF 数据上下文对象中检索的。但是,在我们的应用程序中,每个存储库都创建自己的数据上下文对象。因此,当我们尝试使用我们自己的架构执行与上述相同的操作时:

UserRepository userRepo = new UserRepository();
RoleRepository roleRepo = new RoleRepository();
User user = userRepo.GetUser("Fred");
Role roleToAdd = roleRepo.GetRole("Admin");
user.Roles.Add(roleToAdd);
userRepo.SaveChanges();

我们得到这个错误:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

集中此数据上下文的最佳方式是什么?显然,我不想在 UserRepository 中复制 GetRole 方法,因为那会是多余和愚蠢的。我可以在 UserRepository 上做一个更详细的方法,它接受用户名和角色名,然后使用相同的数据上下文来检索和关联它们,如下所示:

public void AddUserToRole(string username, string role)
{
    User user = dataContext.Users.Single(x => x.Username == username);
    Role roleToAdd = dataContext.Roles.Single(x => x.Name == role);
    user.Roles.Add(roleToAdd);
}

然后我可以这样做:

userRepo.AddUserToRole("Fred", "Admin");
userRepo.SaveChanges();

但这是实现这一目标的最佳方式吗?有没有更好的方法来集中每个请求的 EF 数据上下文,以便所有存储库使用相同的而不是创建自己的存储库?如果是这样,我该怎么做?

最佳答案

在存储库上使用构造函数注入(inject)来传递上下文。

public class UserRepository : IUserRepository
{
    Entities dataContext;

    public UserRepository(Entities entities)
    {
       this.dataContext = entities;
    }

    public User GetUser(string username)
    {
        return dataContext.Users.SingleOrDefault(x => x.Username == username);
    }

    // ... more CRUD-style methods that are not relevant to this question.

    public void SaveChanges()
    {
        dataContext.SaveChanges();
    }
}

告诉您的 DI 容器在上下文生命周期内请求作用域。

例如,使用 AutoFac,您将:

builder.RegisterType<Entities>().InstancePerHttpRequest();
builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerHttpRequest();
builder.RegisterControllers(typeof(MvcApplication).Assembly);

关于c# - 您如何在 Web 应用程序中集中 Entity Framework 数据上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6750557/

相关文章:

c# - 如何在 C# 中访问另一个类中的列表

c# - 如何使用NEST(C#)在Elasticsearch中上传/索引GeoJson文件

linq - LInq 中的 Sum(AND(column))

c# - 一个 DbSet 的 EF 代码优先 PluralizingTableNameConvention

c# - .NET 4.0、MVC 2、 Entity Framework 4 和存储库模式

c# - 正则表达式类 - 缺少程序集引用?

c# - Entity Framework : The underlying provider failed on Open - through WCF service

c# - Fluent Entity Framework 映射

c# - 无效的对象名称异常指的是我尚未创建的对象

c# - 如何在维护关系的同时最好地扩展 Entity Framework 生成的 POCO 对象