Why does Entity Framework Core 2.2 C# respond with an error while inserting a new entity with an existing nested entity

2

I am working on a ASP.NET Core 2.2 project and I am using Entity Framework Core 2.2 as the ORM for accessing an Azure SQL database.

I have the following two entities/tables which are related to eachother (One-To-Many relationship).

[Table("Users")]
public class UserEntity : BaseGuidEntity
{
    .../// other properties

    [ForeignKey("Language")]
    public int LanguageId { get; set; }

    public virtual UserLanguageEntity Language { get; set; }
}

[Table("UserLanguages")]
public class UserLanguageEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    ..//other properties
    public virtual ICollection<UserEntity> Users { get; set; }
}

I have two different languages already inserted in the database. These two are the only available languages, and no new languages are allowed to be inserted. I use the following code to insert a new user with the related language:

var language = _languageRepository.GetById(newUser.Language.Id);

        newUser.LanguageId = language.Id;
        newUser.Language = language;

        _userRepository.Insert(newUser);

So, I basically want to create a new user with the related existing language as well. But what entity framework core attempts, is creating a new language entity with the already existing values, which will ofcourse cause errors in the SQL db.

Error: System.Data.SqlClient.SqlException (0x80131904): Cannot insert explicit value for identity column in table 'UserLanguages' when IDENTITY_INSERT is set to OFF.

How can I related an existing language record to a new user entity?

c#
.net
sql-server
asp.net-core
entity-framework-core
asked on Stack Overflow Aug 13, 2019 by Abed G. • edited Aug 13, 2019 by Abed G.

1 Answer

2

Have you tried not to set newUser.Language? There should be no reason for you to do that since you have set LanguageId. Your GetById method _languageRepository.GetById(newUser.Language.Id); has probably disposed of the context and Insert method is registering that Language object that you are setting and trying to insert it.

Here is how I retrieve entities in my generic repo, maybe this can help you:

public IEnumerable<T> FindBy(Expression<Func<T, bool>> whereCondition, params Expression<Func<T, object>>[] includes)
    {
        IQueryable<T> query = _dbContext.Set<T>().Where(whereCondition);

        if (includes.Any())
            return Includes(includes, query);

        return query;
    }

protected IQueryable<T> Includes(Expression<Func<T, object>>[] includes, IQueryable<T> query)
    {
        return includes.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
    }

And then you can use it like:

FindBy(r => r.Id == id, incl => incl.Languages)
answered on Stack Overflow Aug 13, 2019 by Nemanja Todorovic • edited Aug 13, 2019 by Nemanja Todorovic

User contributions licensed under CC BY-SA 3.0