MVC 5 IdentityDbContext和DbContext事务

时间:2015-01-26 11:52:39

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

我使用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,然后创建一个User。我们假设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不支持指定的类型成员'UserName'。仅支持初始值设定项,实体成员和实体导航属性。位于以下行:

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

1 个答案:

答案 0 :(得分: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,这有时令人沮丧。