【问题标题】:Entity Framework Inserts the entity Already Exists in Database实体框架插入已存在于数据库中的实体
【发布时间】:2017-12-13 08:59:27
【问题描述】:

我正在使用 EF 6 Code-First MVC plus Identity

我自定义了 Identity 框架中定义的标准 ApplicationUser 类,当我尝试通过我的网页注册新用户时,EF 尝试插入数据库中已经存在的实体。

//some code above here

using (ApplicationDbContext db = new ApplicationDbContext())
{
    // I load the City object form db based on the model passed to current method
    City city = db.Countries.Include("States.Cities")
        .First(c => c.Code == model.CountryCode)
        .States.First(s => s.Id == model.StateId)
        .Cities.First(ci => ci.Name == model.CityName);

    // I create a new Employee and a new Company and Company has an Address 
    // referring to the City I loaded from db
    Employee employee = new Employee
    {
        FirstName = model.FirstName,
        LastName = model.LastName,
        Company = new Company
        {
            Name = model.CompanyName,
            OfficePhone = model.OfficePhone,
            Address = new Address { City = city, Street = model.Street, ZipCode = model.ZipCode }
        }
    };

    // This is part of Identity framework code
    var user = new ApplicationUser
    {
        UserName = model.Email,
        Email = model.Email,
        // my custom code: I assign employee to the standard ApplicationUser class
        UserProfile = employee
    };

    // This is going to save the new user to database, 
    // but it tries to insert a new Country object into db. 
    // Note that City class has a property of type State 
    // and State class has a property type of Country 
    var result = await UserManager.CreateAsync(user, model.Password);

    // more code below

根据我得到的错误,听起来 EF 正在将 Country 实体插入到数据库中。我猜当 EF 将地址添加到 db 时会发生这种情况。在我的代码中,Address 是新对象,但 City、State 和 Country 已经存在,您会看到我一开始是从 db 加载 City。所以我尝试使用下面的代码,但它没有帮助:

db.Entry(employee.Company.Address.City).State = EntityState.Unchanged;

抱歉,代码太长了,不过我尽量减少它。

这是我的模型:

public class Country
{
    string Code;
    string Name;
    List<State> States;
}

public class State
{
    int Id;
    string Name;
    List<City> Cities;
}

public class City
{
    int Id;
    string Name;
    State State;
}

public class Address
{
    string Street;
    string ZipCode;
    City City;
}

public class Company
{
    string Name;
    string OfficePhone;
    Address Address;
}

【问题讨论】:

  • EF 尝试添加哪个实体? City ?你能告诉我们实体声明吗?
  • 这个问题与 EF 的行为有关,它将预先附加的附着实体标记为“已添加”。由于所有相关实体似乎都有一定的关系,因此需要显示每个相关类以进行分析(CountryStateCity & Address)。
  • 你能显示Address类的代码吗?
  • 感谢 cmets。我添加了我的模型。希望你有你需要的所有信息。
  • @GGO,我更新了我的帖子来回答你的问题

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


【解决方案1】:

我很久以前就遇到过类似的问题。我不知道问题所在,但我有一个解决方法:

替换代码:

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

下面的代码:

var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
var result = UserManager.Create(user, model.Password);

这将正确保存数据。

【讨论】:

    【解决方案2】:

    问题是,您每次都在创建新对象。您需要先执行测试以查看用户是否存在,如果存在则使用现​​有数据填充对象并使用更新。所以你还需要考虑使用UserManager.UpdateAsync方法。

    【讨论】:

    • 实际上我正在创建新对象,因为这是注册控制器。我创建了一个新用户、新公司和新用户配置文件。但是 City 是从 db 加载的。你为什么说我不应该那样做?!
    • 您说该实体已经存在。如果它存在,那么您需要执行更新或根本不执行任何操作。关于您的地址,如果它已经存在,那么您不应该针对用户创建新的地址对象。相反,您应该将地址的 ID 分配给用户的地址 ID 以建立链接。
    • 用户实体是新的,地址也是新的,分配给用户,但城市、州和国家/地区已存在于数据库中。请查看我的问题。
    • 通常City City 地址中的声明我希望看到声明为虚拟。其他人也一样。
    猜你喜欢
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2022-01-01
    • 1970-01-01
    相关资源
    最近更新 更多