簡體   English   中英

如何在 web 應用程序中集中實體框架數據上下文?

[英]How do you centralize the Entity Framework data context in a web application?

在我們的應用程序中,我們使用存儲庫模式從我們的數據存儲介質中檢索和持久化數據。 我們選擇使用的媒介是 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();
    }
}

用戶和角色實際上在實體框架 model 中具有多對多關系。 有時我們想要獲取現有用戶和現有角色並將兩者關聯起來。 通常,如果您執行如下簡短的示例代碼片段,這將非常有用:

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 數據上下文 object 中檢索的。 但是,在我們的應用程序中,每個存儲庫都會創建自己的數據上下文 object。 因此,當我們嘗試對我們自己的架構進行與上述相同的操作時:

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

我們得到這個錯誤:

無法定義這兩個對象之間的關系,因為它們附加到不同的 ObjectContext 對象。

集中此數據上下文的最佳方法是什么? 顯然,我不想在 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 數據上下文,以便所有存儲庫使用相同的存儲庫而不是創建自己的存儲庫? 如果是這樣,我該怎么做?

在存儲庫上使用構造函數注入來傳遞上下文。

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

我們遇到了完全相同的問題。 您應該使用工作單元設計模式。 在此處閱讀更多信息: http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0。 aspx

就個人而言,我更喜歡傳遞用戶名和角色的方法,它在存儲庫中具有用於將用戶添加到數據庫的所有數據庫邏輯。 如果您調用此方法 10 次,您將不希望獲取角色並將其添加到 MVC 應用程序中 10 個不同位置的用戶 object。

讓存儲庫完成所有工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM