【问题标题】:Primary Key issues when Migrating "Legacy" SQLite Databases to use the Entity Framework迁移“旧版”SQLite 数据库以使用实体框架时的主键问题
【发布时间】:2023-03-05 18:58:01
【问题描述】:

我最近开始了一个已经运行了几年的项目。该应用程序是用 c# 编写的,使用 Windows 窗体作为 UI,SQLite 用于数据库。当前使用 ADO.NET 通过 System.Data.SQLite 命名空间访问该数据库。

客户端不时收到应用程序和数据库更新,但并非一次全部更新,因此存在大量结构不同的数据库版本。更糟糕的是,客户可以将自己的字段添加到应用程序的表中以启用自定义报告等。因此,不同数据库的数量是失控的。当功能增强后,添加了越来越多的“if-then-else”代码,以保持应用程序针对所有这些数据库变体运行。

除此之外,SQLite 有一个令人讨厌的特性,即字段中的值可以存储为任何类型,而不仅仅是 table create 语句中定义的类型。通常从 Excel 的 CSV 文件中导入数据,这些文件的日期/时间值不正确,SQLite 很乐意导入这些数据,但在代码中我们会遇到各种无效类型异常。

我想阻止这一切。

为了清理数据库,我正在倡导一种标准的数据库设计,除非我们发布官方更新以及自动迁移数据的代码,否则这种设计不会改变。

我采用了最新的“临时”设计,并且在不更改表和字段名称的情况下,通过确保为现有字段定义主键并使用一致的类型,使其至少对实体框架友好。

我现在正尝试逐一迁移各种旧数据库。我正在使用一种技术,使用“SELECT * FROM [LEGACY_TABLE];”加载每个表中的所有记录并使用new EF_Table() { ID = GetValue<long>(dr, "ID"), Description = GetValue<string>(dr, "Description"), }; 创建新的实体框架对象。我定义了GetValue 来处理格式错误的数据和DBNull 引用等的转换。

我现在的主要问题是许多表的主键定义为“INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL”,这不允许实体框架从旧数据库分配当前键值。

在迁移过程中,我需要确保主键保持不变,因为没有定义外键关系,并且现有的主键值存储在数据库之外的应用程序配置数据中。

我四处寻找解决方案,但没有找到。我会认为这种问题 - 现有 SQLite 数据库的迁移和/或清理 - 将是一个已解决的问题。

谁能指出我解决这个问题的有效方向?

【问题讨论】:

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


    【解决方案1】:

    嗯,解决这个问题很简单。

    事实证明,实体框架在“edmx”文件中定义的主键有一个属性StoreGeneratedPattern="Identity",用于自动递增主键。通过将值更改为StoreGeneratedPattern="None",实体框架允许通过代码中的简单赋值来更新主键。

    所以,例如,当我有这个表定义时:

    CREATE TABLE "FM_Location" (
        [ID] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
        [Location] TEXT
    );
    

    然后在“edmx”文件中定义以下“EntityType”元素:

    <EntityType Name="FM_Location">
        <Key>
            <PropertyRef Name="ID" />
        </Key>
        <Property Name="ID" Type="integer" Nullable="false"
                StoreGeneratedPattern="Identity" />
        <Property Name="Location" Type="nvarchar" />
    </EntityType>
    

    我将“身份”更改为“无”,如下所示:

    <EntityType Name="FM_Location">
        <Key>
            <PropertyRef Name="ID" />
        </Key>
        <Property Name="ID" Type="integer" Nullable="false"
                StoreGeneratedPattern="None" />
        <Property Name="Location" Type="nvarchar" />
    </EntityType>
    

    我对所有自动增量字段都进行了此操作,并且可以进行迁移。

    【讨论】:

      猜你喜欢
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-04
      相关资源
      最近更新 更多