skip to Main Content

When I insert a new MaskField model into my database using Entity Framework Core it also inserts a Restriction model which is referenced inside the MaskField model. I am trying to get it to only reference a Restriction object as I already know the object exists when trying to reference it inside MaskField.

I have a MaskField model defined:

[Table("MaskField", Schema = "dbo")]
public class MaskField
{
    [Key]
    public int maskId { get; set; }
        public Restriction? restriction { get; set; }
}

That MaskField model references a single Restriction model inside it. This is the Restriction model:

[Table("Restriction", Schema = "dbo")]
public class Restriction
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int restrictionId { get; set; }
    [Required]
    public string? restrictionName { get; set; }
    [Required]
    public string? regex { get; set; }
}

My DbContext:

public class MaskContext : DbContext
{
    public MaskContext(DbContextOptions options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MaskField>((mf) =>
        {
            mf.HasKey(e => new { e.maskId });
            mf.HasOne(e => e.restriction).WithMany();
        });
    }

    public DbSet<MaskField> MaskFields { get; set; }
    public DbSet<Restriction> Restrictions { get; set; }
}

Trying to insert a MaskField that contains a restriction ends up executing:

INSERT INTO [dbo].[Restriction] ([restrictionId], [regex], [restrictionName])
VALUES (@p0, @p1, @p2); 

Which ends up erroring because IDENTITY_INSERT is disabled. Any ideas on how to just reference it instead of it trying to insert a new Restriction model?

EDIT: This is the code for inserting a MaskField

public class MaskRepository : IMaskRepository
{
    MaskContext dbContext;
    public MaskRepository(MaskContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public async Task<MaskField> CreateAsync(Mask _object)
    {
        var obj = await dbContext.MaskFields.AddAsync(_object);
        dbContext.SaveChanges();
        return obj.Entity;
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    I have found a not so nice workaround for this.

    So to just reference the Restriction is fairly simple just change the line public Restriction? restriction {get;set;} to reference the key for Restriction like: public int? restrictionId {get;set;}

    However since I wanted to extract the whole Restriction object in the one query I was forced to have both fields like this:

    [Table("MaskField", Schema = "dbo")]
    public class MaskField
    {
        [Key]
        public int maskId { get; set; }
        
        public int? restrictionId { get; set; }
        public Restriction? restrictionId { get; set; }
    }
    

    This seems like a good solution until I realised that when saving/ updating that object to the database it causes the same original problem.

    To work around this I have added logic in the saving and updating functions to set those fields to null before saving:

    public class MaskRepository : IMaskRepository
    {
        MaskContext dbContext;
        public MaskRepository(MaskContext dbContext)
        {
            this.dbContext = dbContext;
        }
    
        public async Task<MaskField> CreateAsync(MaskField _object)
        {
            _object.restriction = null;
    
            var obj = await dbContext.MaskFields.AddAsync(_object);
            dbContext.SaveChanges();
            return obj.Entity;
        }
    }
    

  2. Finally found a proper resolution to this problem.
    You can add the [JsonIgnore] field to model classes to stop models from even being submitted to ef core in the first place.

    In this case it will be:

    [Table("MaskField", Schema = "dbo")]
    public class MaskField
    {
        [Key]
        public int maskId { get; set; }
        
        public int? restrictionId { get; set; }
        [JsonIgnore]
        public Restriction? restriction { get; set; }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search