我最近开始研究已经运行了几年的项目。该应用程序使用Windows窗体(用于UI)和SQLite(用于数据库)以c#编写。当前使用ADO.NET通过System.Data.SQLite
命名空间访问数据库。
有时候客户端已经收到应用程序和数据库更新,但不是一次全部,因此存在许多结构不同的数据库版本。更糟糕的是,客户端能够将自己的字段添加到应用程序的表中以启用自定义报告等。因此,不同数据库的数量不受控制。当功能增强时,已经添加了越来越多的“if-then-else”代码,以保持应用程序针对所有这些数据库变体运行。
除此之外,SQLite还有一个令人讨厌的功能,即字段中的值可以存储为任何类型,而不仅仅是表create语句中定义的类型。从Excel文件中导出数据的常见情况是,这些数据具有SQLite愉快导入的错误日期/时间值,但在代码下,我们会获得各种无效类型异常。
我想停止这一切。
为了清理数据库,我正在发起一个不会改变的标准数据库设计,除非我们发布官方更新以及自动迁移数据的代码。
我采用了最新的“ad-hoc”设计,并且在不更改表和字段名称的情况下,通过确保为现有字段定义主键并使用一致类型,使得至少实体框架友好。
我现在正在尝试逐个迁移各种旧数据库。我正在使用一种技术,使用“SELECT * FROM [LEGACY_TABLE];”加载每个表中的所有记录。并使用new EF_Table() { ID = GetValue<long>(dr, "ID"), Description = GetValue<string>(dr, "Description"), };
创建新的Entity Framework对象。我已经定义GetValue
来处理转换格式错误的数据和DBNull
引用等。
我现在的主要问题是许多表都将主键定义为“INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL”,这将不允许实体框架从旧数据库中分配当前键值。
在迁移过程中,我需要确保主键保持不变,因为没有定义外键关系,现有主键值存储在应用程序配置数据中的数据库之外。
我已经四处寻找解决方案,但看不到一个。我本以为这种问题 - 迁移和/或清理现有的SQLite数据库 - 本来就是一个已经解决的问题。
有人能指出我有效的方向来解决这个问题吗?
答案 0 :(得分: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>
我在所有自动增量字段中都这样做了,我可以进行迁移。