«Значение не может быть нулевым» при использовании автоинкремента / ValueGeneratedOnAdd с EF Core + SQLite - PullRequest
1 голос
/ 13 февраля 2020

У меня есть 2 сущности Movie и MovieVersion, которые наследуют следующий абстрактный класс, определяющий свойство 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);

И получаю эту ошибку: «Значение не может быть нулевым. (Параметр« ключ »)». Что может пойти не так? Я думал, что раньше это работало, но теперь что-то изменилось. Я нахожусь на 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);
    }
}

DbContext:

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);
    }
}

Seed :

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

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 27 апреля 2020

Я думаю, что вы используете sql lite, у которого нет столбца идентификаторов. Это AUTOINCREMENT в sql lite использовать правильную платформу. Чтобы использовать поставщик базы данных SQLite, первым делом необходимо установить пакет NuGet Microsoft.EntityFrameworkCore.Sqlite.

ИЛИ выполните ручной способ исправления таблицы. EF ищет БД и создает столбец идентификаторов в синтаксисе SQL. Удалите ваши данные Миграция. Попробуйте сменить стол так.

CREATE TABLE COMPANY(
   ID INTEGER PRIMARY KEY AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);
0 голосов
/ 25 апреля 2020

В вашем интерфейсе сущностей нет установщика, может быть, вам стоит подумать о том, чтобы изменить его следующим образом

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