实体框架再次插入现有的引用实体

时间:2015-01-07 15:54:08

标签: c# entity-framework

我的代码真的不怎么样。

我尝试使用现有实体(Location)并将其用作另一个实体(ApplicationUser)的属性之一。

我希望ApplicationUser引用现有的Location,但它会创建一个新的Location并引用它。

以下是实体:

public class ApplicationUser : IdentityUser
{
    public int? LocationId { get; set; }
    public Location Location { get; set; } 
}


public class Location
{
    public Location()
    {
        this.Users = new HashSet<ApplicationUser>();
    }

    public int LocationId { get; set; }
    public string Country { get; set; }
    public string Province { get; set; }
    public string Area { get; set; }

    public virtual ICollection<ApplicationUser> Users { get; set; }
}

以下是我的配置:

public class ApplicationUserConfiguration : EntityTypeConfiguration<ApplicationUser>
{
    public ApplicationUserConfiguration()
    {
        this.HasOptional(i => i.Location)
            .WithMany(i => i.Users)
            .HasForeignKey(i => i.LocationId);
    }
}

public class LocationConfiguration : EntityTypeConfiguration<Location>
{
    public LocationConfiguration()
    {
        this.HasKey(i => i.LocationId);
        this.Property(i => i.Country).HasMaxLength(100);
        this.Property(i => i.Province).HasMaxLength(100);
        this.Property(i => i.Area).HasMaxLength(100);
    }
}

以下是我保存位置的方法:

public Task SaveAsync(IUnitOfWork unitOfWork, Location entity)
{
        var context = (ApplicationDbContext)unitOfWork.Context;
        context.Entry(entity).State = entity.LocationId == 0
           ? EntityState.Added
           : EntityState.Modified;
        return context.SaveChangesAsync();
}

在我的代码中,我首先预先填充位置。 然后我将现有位置称为用户的位置。

//successfully called an existing location. LocationId is 5
var adminLocation = await this._locationService.FindByArea("Philippines", "Laguna", "Calamba");

admin = new ApplicationUser
            {
               LockoutEnabled = false,
               Email = Settings.Default.DefaultAdminEmail,
               UserName = Settings.Default.DefaultAdminUserName,
               FirstName = "admin",
               LastName = "yow",

               // used here
               Location = adminLocation
             };

// save user
var identityResult = await this._userService.RegisterUserAsync(admin, 
    Settings.Default.DefaultAdminPassword);

执行后,检查数据库后,我会得到以下图片。

我仍然想知道为什么它保存了一个新位置。 当我调试我的应用程序时,它在创建用户时不会调用位置保存方法。

我的配置可能有什么问题吗? 谢谢你们。

位置表:

enter image description here

用户表使用错误的位置:

enter image description here

1 个答案:

答案 0 :(得分:1)

它会给你重复,因为你设置了错误的字段。您应该使用要使用的LocationID记录的ID设置Location本身,而不是导航属性。 EF这样做是因为它更注重ID,而不是导航属性上的ID。当它看到对象上存在Location条记录,但看到LocationID为0时,它会假定用户打算创建一个全新的Location,从而会创建一个新的{{1}}一进入数据库。

这听起来很荒谬,我知道,但这对你来说是EF。

我写了一篇关于这篇文章的博文,其中有关于同一问题的更多信息here

相关问题