首页 > 解决方案 > Entity Framework Core 接收 0 以作为 Id 播种,尽管我将其定义为其他内容

问题描述

尝试添加迁移时,ef core 给我以下错误:

无法添加实体类型“MyEntity”的种子实体,因为属性“Id”需要非零值。考虑提供一个负值以避免与非种子数据发生冲突。

实体 MyEntity 及其超类/接口:

public class MyEntity: EntityObject
{
    public long OrderId { get; set; }
    public List<StateChange> StateChanges { get; set; }
}

public class EntityObject : IEntityObject
{
    [Key]
    public int Id { get; set; }        
    [Timestamp]
    public byte[] RowVersion
    {
        get;
        set;
    }
}
public class IEntityObject
{
    int Id { get; set; 
    byte[] RowVersion { get; set; }
}

播种:

 var seed = new MyEntity{ Id = -2, StateChanges = new List<StateChange>(), OrderId = -2 };
 modelBuilder.Entity<MyEntity>().HasData(seed);

我一直在尝试使用 [Key] 和 [DatabaseGenerated] 进行各种尝试,但找不到解决方案。所有ef core nuget依赖的版本都是3.1.5

标签: c#.net-coreentity-framework-coreentity-framework-core-3.1

解决方案


将类 更改IEntityObject接口

这是一个完全正常工作的控制台项目,假设它StateChange是您的一些内部类,而不是模型/实体类:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public interface IEntityObject // <-- changed from `class` to `interface`
    {
        int Id { get; set; }
        byte[] RowVersion { get; set; }
    }

    public class EntityObject : IEntityObject
    {
        [Key]
        public int Id { get; set; }   
        
        [Timestamp]
        public byte[] RowVersion
        {
            get;
            set;
        }
    }

    public class MyEntity : EntityObject
    {
        public long OrderId { get; set; }
        public List<StateChange> StateChanges { get; set; }
    }
        
    public class StateChange
    {
    }
    
    public class Context : DbContext
    {
        public DbSet<MyEntity> MyEntities { get; set; }
        
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(@"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So62865284")
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyEntity>(
                entity =>
                {
                    entity.Ignore(e => e.StateChanges); // <-- ignore your internal class
                    
                    entity.HasData(
                        new MyEntity
                        {
                            Id = 2,
                            StateChanges = new List<StateChange>(),
                            OrderId = 2
                        });
                });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var myEntitiesWithStateChanges = context.MyEntities
                .OrderBy(i => i.Id)
                .ToList();
            
            Debug.Assert(myEntitiesWithStateChanges.Count == 1);
        }
    }
}

如果StateChange它也应该是一个模型类/实体,那么你应该向它添加一个外键并设置关系。这可能看起来像这样:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public interface IEntityObject // <-- changed from `class` to `interface`
    {
        int Id { get; set; }
        byte[] RowVersion { get; set; }
    }

    public class EntityObject : IEntityObject
    {
        [Key]
        public int Id { get; set; }   
        
        [Timestamp]
        public byte[] RowVersion
        {
            get;
            set;
        }
    }

    public class MyEntity : EntityObject
    {
        public long OrderId { get; set; }
        public List<StateChange> StateChanges { get; set; } = new List<StateChanges>();
    }
        
    public class StateChange : EntityObject
    {
        public int MyEntityId { get; set; } // <-- added FK
        public MyEntity MyEntity { get; set; } // <-- added navigation property
    }
    
    public class Context : DbContext
    {
        public DbSet<MyEntity> MyEntities { get; set; }
        public DbSet<StateChange> StateChanges { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(@"Data Source=.\MSSQL14;Integrated Security=SSPI;Initial Catalog=So62865284")
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyEntity>(
                entity =>
                {
                    // Added the relationship definition (not really necessary here,
                    // because this would also work by convention).
                    entity.HasMany(e => e.StateChanges)
                        .WithOne(s => s.MyEntity)
                        .HasForeignKey(s => s.MyEntityId);

                    entity.HasData(
                        new MyEntity
                        {
                            Id = 2,
                            OrderId = 2
                        });
                });
            
            modelBuilder.Entity<StateChange>(
                entity =>
                {
                    entity.HasData(
                        new StateChange
                        {
                            Id = 2,
                            MyEntityId = 2,
                        });
                });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var myEntitiesWithStateChanges = context.MyEntities
                .Include(e => e.StateChanges)
                .OrderBy(i => i.Id)
                .ToList();
            
            Debug.Assert(myEntitiesWithStateChanges.Count == 1);
            Debug.Assert(myEntitiesWithStateChanges[0].StateChanges.Count == 1);
        }
    }
}

推荐阅读