【问题标题】:MVC 5 IdentityDbContext and DbContext transactionsMVC 5 IdentityDbContext 和 DbContext 事务
【发布时间】:2015-01-26 11:52:39
【问题描述】:

我使用 EF6.1 处理 MVC 5 项目。作为初学者,我尝试保留 MVC 5 模板生成的代码,以便将默认身份验证系统与 AccountController 一起使用。 但是,我必须添加一些类,例如下面的“User.cs”,所以我使用的是实体框架数据模型。

public partial class User
{
    public User()
    {
        this.Logs= new HashSet<Log>();
    }

    public int IdUser { get; set; }
    public string AspNetUsersId { get; set; } //References to AspNetUsers.Id
    public string Title { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Job{ get; set; }

    public virtual ICollection<Log> Logs { get; set; }
}

所以,我有两种情况:

public partial class MyEFDataModelContainer : DbContext
{
    public MyEFDataModelContainer ()
        : base("name=MyEFDataModelContainer")
    {
    }

    public DbSet<User> Users { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }
}

所以,我的场景是我需要创建一个 AspNetUsers,然后向这个 AspNetUsers 添加一个 AspNetRoles,然后创建一个用户。我们假设 AspNetUsers 创建和 AspNetRoles 工作,但如果用户创建失败,我该如何回滚 AspNetUsers 和 AspNetRoles?

我可以使用这两个上下文创建事务吗?

很遗憾,我还需要调用 WCF webservices 来执行这个任务?我能做什么?

最好的问候,

更新

我的合并上下文:

public partial class User: IdentityUser { }
public partial class MyEFDataModelContainer : IdentityDbContext<User> 
{ 
public MyEFDataModelContainer() : base("name=MyEFDataModelContainer") 
{ }
}

我的 AccountController.cs:

public class AccountController : Controller
{
    public AccountController()
    {
       UserManager =new UserManager<User>(new UserStore<User>(new MyEFDataModelContainer()))
    }
    public UserManager<User> UserManager {get;set;}
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new USER() { UserName = model.UserName, Email = model.Email, PhoneNumber = model.Phone };
            var result = await UserManager.CreateAsync(user, model.Password);
            var role = await UserManager.AddToRoleAsync(user.Id, "Membre");
            if (result.Succeeded)
            {
                using (UserBusiness business = new UserBusiness())
                {
                    var userResult = business.AddUser(model.FirstName, model.LastName, user.Id);
                }

                await SignInAsync(user, isPersistent: false);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }
        return View(model);
    }
}

我的 Web.config :

<connectionStrings>    
<add name="MyEFDataModelContainer" connectionString="metadata=res://*/MyEFDataModel.csdl|res://*/MyEFDataModel.ssdl|res://*/MyEFDataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=localhost;initial catalog=DB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

但现在,我遇到了错误 LINQ to Entities 不支持指定的类型成员“用户名”。仅支持初始化器、实体成员和实体导航属性。在以下行:

var result = await UserManager.CreateAsync(user, model.Password);

【问题讨论】:

    标签: c# asp.net-mvc entity-framework transactions asp.net-mvc-5


    【解决方案1】:

    那么,我的第一个问题是,为什么需要两个上下文?是否有理由将 aspnet 表与业务表分开?

    你能不能这样做:

    public partial class MyEFDataModelContainer : IdentityDbContext<User>
    {
        public MyEFDataModelContainer ()
            : base("name=MyEFDataModelContainer")
        {
        }
    
        public DbSet<User> Users { get; set; }
    }
    

    确保您的自定义 User 类继承自 IdentityUser。

    public partial class User : IdentityUser
    {
        public User()
        {
            this.Logs= new HashSet<Log>();
        }
    
        public int IdUser { get; set; }
        public string AspNetUsersId { get; set; } //References to AspNetUsers.Id
        public string Title { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Job{ get; set; }
    
        public virtual ICollection<Log> Logs { get; set; }
    }
    

    然后,将您的 AccountController 更改为此连接字符串。这样,所有内容都在同一个数据库中。

    public class AccountController : Controller
    {
        public AccountController()
            : this(new UserManager<User>(
                   new UserStore<User>(new MyEFDataModelContainer())))
        {
        }
    }
    

    虽然,要回答您的问题,是的,您可以在事务中包装对两个上下文的访问。但是,您将不得不处理 MSDTC,根据我的经验,这有时会令人沮丧。

    【讨论】:

    • 我尝试合并这两个上下文,现在我有:public class ApplicationUser : IdentityUser { } public partial class MyEFDataModelContainer : IdentityDbContext&lt;ApplicationUser&gt; { public MyEFDataModelContainer() : base("name=MyEFDataModelContainer") { } 但我尝试登录时出错:实体类型 ApplicationUser 不是当前模型的一部分上下文 我需要在数据模型中创建实体吗?
    • @madhatterx 抱歉,我想我错过了答案中的一步。您希望自定义 User 类从 IdentityUser 实现,然后将您的 User 类传递给 IdentityDbContext 基类。
    • 是否可以合并 AspNetUsers 表和我的自定义用户表?
    • @madhatterx,是的,这就是我想要达到的目的。如果您的 User 类继承自 IdentityUser,它应该将您的自定义内容合并到 aspnet_users 表中。
    • 我已经更新了我的上下文,我的 AccountController 并且出现了以下错误:LINQ to Entities 不支持指定的类型成员“用户名”。在var result = await UserManager.CreateAsync(user, model.Password); 行仅支持初始化器、实体成员和实体导航属性
    猜你喜欢
    • 1970-01-01
    • 2015-01-08
    • 2018-07-07
    • 2011-08-27
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    相关资源
    最近更新 更多