实体框架:CreateAsync上的重复键(Idendity方法)

时间:2016-01-20 23:08:23

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

我在数据库中插入数据时遇到了重复的密钥问题。出现问题是因为Seed方法的实现我插入了一些默认值。

之后,我创建了一个具有复杂关系的用户的注册表,遵循以下代码:

种子()

//Counties
context.Countie.AddOrUpdate(
    c =>  c.NameId ,
    new County { NameId = "Antrim" },
    new County { NameId = "Armagh" },
    new County { NameId = "Carlow" },
    new County { NameId = "Cavan" },
    new County { NameId = "Clare" },
    new County { NameId = "Cork" },
    new County { NameId = "Derry" },
    new County { NameId = "Donegal" },
    new County { NameId = "Down" },
    new County { NameId = "Dublin" },

注册

public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser
        {
            UserName = model.Email,
            Email = model.Email,
            BornDate = model.BornDate,
            Name = model.Name,
            Gender = model.Gender,
            Price = model.Price,
            UserType = model.UserType,
            PhoneNumber = model.PhoneNumber
        };
        if (model.Photo != null && model.Photo.ContentLength > 0)
            user.PhotoPath = $"\\Content\\UsersPhotos\\{FileUploaderHelper.Upload(model.Photo, model.UserType, user.Id)}";

        user.Address = new Address
        {
            Id = Guid.NewGuid().ToString(),
            StreetAddress = model.StreetAddress,
            PostalCode = model.PostalCode,
            Number = model.StreetNumber
        };
            user.Address.City = new City
        {
            Id = Guid.NewGuid().ToString(),
            Name = model.City,
            County = new County { NameId = model.CountyId }
        };
            var geocoded = GeocodeHelper.GetGeoCodedAddress(user.Address);
        user.Address.Latitude = geocoded.Coordinates.Latitude.ToString().Replace(",",".");
        user.Address.Longitude = geocoded.Coordinates.Longitude.ToString().Replace(",", ".");

        try
        {
            var result = await UserManager.CreateAsync(user, model.Password); //error occurs here

我认为错误是因为我正在实例化一个新对象。但是正确的做法是什么?

以下关系如下:

地址 - &gt;城市 - &gt;县

它可以是: 每个地址都有一个城市,而这个城市又有一个县。

enter image description here

1 个答案:

答案 0 :(得分:0)

做这样的事情:

SELECT * 
FROM DB 
WHERE (Money > 100 AND Currency = 'USD' OR Money2 > 200 AND Currency2 = 'EUR')

从上下文中获取县记录并使用它而不是创建新记录。

更新

如果你有像这样的UserManager实现,那么你可以简单地覆盖它的行为。

ApplicationDbContext db = new ApplicationDbContext();

Country county = db.Countie.FirstOrDefault(c => c.NameId == model.CountyId);

if(county == null)
{
     ModelState.AddModelError("", "Invalid County");
}
else
{
    user.Address.City.County = county;
}

确保使用的是ApplicationManager。在你的Startup中添加:

 public class ApplicationUserManager : UserManager<ApplicationUser>
 {
    public ApplicationUserManager(IUserStore<ApplicationUser> store)
        : base(store)
    {
    }

    public override System.Threading.Tasks.Task<IdentityResult> CreateAsync(ApplicationUser user, string password)
    {
        return base.CreateAsync(user, password);
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
}