【问题标题】:"Value cannot be null" when using auto-increment/ValueGeneratedOnAdd with EF Core + SQLite将自动增量/ValueGeneratedOnAdd 与 EF Core + SQLite 一起使用时“值不能为空”
【发布时间】:2020-05-28 15:14:04
【问题描述】:

我有 2 个实体 MovieMovieVersion,它们继承了以下抽象类,定义了一个 ID 属性:

public interface IEntity
{
    int Id { get; }
}

public abstract class EntityBase : IEntity
{
    public int Id { get; set; }
}

public class Movie : EntityBase, IAggregateRoot ...

public class MovieVersion : EntityBase ...

我已经设置了以下配置:

public class MovieConfiguration : IEntityTypeConfiguration<Movie>
{
    public void Configure(EntityTypeBuilder<Movie> builder)
    {
        builder.HasKey(m => m.Id);

        builder.Property(m => m.Id).ValueGeneratedOnAdd();

        builder.HasMany(m => m.MovieVersions)
            .WithOne();
    }
}

public class MovieVersionConfiguration : IEntityTypeConfiguration<MovieVersion>
{
    public void Configure(EntityTypeBuilder<MovieVersion> builder)
    {
        builder.HasKey(m => m.Id);

        builder.Property(m => m.Id).ValueGeneratedOnAdd();
    }
}

我尝试使用此代码进行播种:

var movieRepository = new MovieRepository(context);
var movie = new Movie("The Good, the Bad and the Ugly", 1966);
movieRepository.AddMovie(movie);

我得到这个错误:“值不能为空。(参数'key')”。出了什么问题?我以为我以前可以正常工作,但现在发生了一些变化。我正在使用 EF Core v3.1.1 并使用 SQLite。

为了完整起见,这里是存储库的摘录:

public abstract class RepositoryBase<T> where T : class, IAggregateRoot
{
    private readonly ApplicationDbContext _context;

    public RepositoryBase(ApplicationDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    protected DbSet<T> Set => _context.Set<T>();
}

public class MovieRepository : RepositoryBase<Movie>, IMovieRepository
{
    public MovieRepository(ApplicationDbContext context) : base(context) {}

    public void AddMovie(Movie movie)
    {
        Set.Add(movie);
    }
}

数据库上下文:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<Movie> Movies { get; set; }

    public DbSet<MovieVersion> MovieVersions { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());

        base.OnModelCreating(builder);
    }
}

种子:

context.Database.EnsureCreated();

if (context.Movies.Any()) return;

var movieRepository = new MovieRepository(context);
var movieContainerRepository = new MovieContainerRepository(context);

var movie = new Movie("The Good, the Bad and the Ugly", 1966);
movieRepository.AddMovie(movie); // throws mentioned error

提前谢谢你!

【问题讨论】:

  • 配置是否应用正确?参考here。或者你可以参考这个Use IEntityTypeConfiguration with a base entity
  • 1.您是否添加了 DbSet? 2.我不知道 IEntity 在那里做什么 3.如果你所做的只是为每个类添加一个 Id,你也可以继承一个非抽象的 EntityBase 类。
  • @JeffLi 1. 忘记显示 DbContext,但是是的,我已将 DbSets 添加为 properties.2。 IEntity 仅指定 ID 属性。 3. 这对我有什么帮助?
  • @XingZou 是的,我使用扩展 ApplyConfigurationsFromAssembly()。
  • 现在添加了一些缺失的代码。

标签: .net sqlite asp.net-core .net-core entity-framework-core


【解决方案1】:

你的实体接口没有设置器,也许你应该考虑这样改变它

public interface IEntity
{
    int Id { get; set;}
}

【讨论】:

    【解决方案2】:

    我认为您使用的是没有标识列的 sql lite。它在 sql lite 中是 AUTOINCREMENT 使用权框架 要使用 SQLite 数据库提供程序,第一步是安装 Microsoft.EntityFrameworkCore.Sqlite NuGet 包。

    或者做手动校正表的方法 EF 查找 DB 并在 SQL 语法中创建标识列。 删除您的数据迁移。 试着像这样改变你的桌子。

    CREATE TABLE COMPANY(
       ID INTEGER PRIMARY KEY AUTOINCREMENT,
       NAME           TEXT      NOT NULL,
       AGE            INT       NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL
    );
    

    【讨论】:

      猜你喜欢
      • 2019-05-04
      • 2013-05-25
      • 1970-01-01
      • 2019-12-11
      • 1970-01-01
      • 2017-03-13
      • 2015-08-06
      • 2021-11-26
      • 1970-01-01
      相关资源
      最近更新 更多