【问题标题】:How to avoid the AUTOINCREMENT keyword with EFC and SQLite?如何避免 EFC 和 SQLite 的 AUTOINCREMENT 关键字?
【发布时间】:2019-02-27 19:35:39
【问题描述】:

AUTOINCREMENT doesn't usually need to be used in SQLite. 即使没有这个关键字,自动生成的 ID 也可以工作。

但是,当使用 Entity Framework Core(从 2.1.3 开始)和 SQLite 时,整数主键被声明为 AUTOINCREMENT。有没有办法避免这种情况?

我尝试将[DatabaseGenerated(DatabaseGeneratedOption.None)] 属性添加到实体的主键属性,但这完全禁用了自动键生成,我必须为每次插入手动设置它。否则,EFC 会尝试使用显式 Id = 0 插入。

所以我需要将其视为插入时生成的数据库,我只是想避免不必要的 AUTOINCREMENT 关键字。有没有办法做到这一点?

编辑

这是一些示例 C# 代码:

using System;
using Microsoft.EntityFrameworkCore;

namespace Experiments
{
    public class Entity
    {
        public long Id { get; set; }

        public string Text { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<Entity> Entities { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=temp.sqlite");
        }
    }

    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            using (var context = new Context())
            {
                context.Database.EnsureCreated();
            }
        }
    }
}

当使用 SQLite 的 DB Browser 查看时,这将创建一个如下所示的数据库:

我宁愿不将主键声明为 AUTOINCREMENT,这也会创建 sqlite_sequence 表。 SQLite 可以在没有该关键字的情况下生成密钥,而且它更简单、更快。

【问题讨论】:

  • 浏览实体框架文档,我认为不可能不编写自己的自定义后端而不是使用标准的sqlite。

标签: c# .net sqlite .net-core entity-framework-core


【解决方案1】:

据我所知,问题是由当前SqliteMigrationsAnnotationProvider 类中的以下代码引起的:

if (property.ValueGenerated == ValueGenerated.OnAdd
    && property.ClrType.UnwrapNullableType().IsInteger()
    && !HasConverter(property))
{

    yield return new Annotation(SqliteAnnotationNames.Autoincrement, true);
}

这将SqliteMigrationsSqlGenerator 类强制为include AUTOINCREMENT

我不知道这是为什么,我认为这是一个遗留错误,但你最好在他们的问题跟踪器中询问。

查看代码,设置假值转换器似乎可以防止这种情况发生并且可以用作临时解决方法:

modelBuilder.Entity<Entity>()
    .Property(e => e.Id)
    .HasConversion(v => v, v => v);

【讨论】:

  • 感谢您的研究。它可能是设计使然,因为它确实使事物的行为更像传统数据库中的行为。虽然我想知道为什么他们会让价值转换器与此有关。
【解决方案2】:

定义模型类如下。因此,您不会映射 Id 列并使用另一列作为 PK。

[NotMapped]
public override int Id
{
    get
    {
        return PKColumn;
    }
    set
    {
        PKColumn = value;
    }
}

[Key]
public virtual int PKColumn { get; set; }

【讨论】:

  • 这不会改变架构,它只是将主键列的名称设置为 PKColumn。
  • @relatively_random 您需要删除自动生成身份的代码,如果您在该实体的 DBContext 中有..然后添加迁移并运行 update-database 命令
  • 我不明白。自动生成身份的代码是什么?
  • @relatively_random 你能发布 DBCONTEXT
猜你喜欢
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
相关资源
最近更新 更多