【问题标题】:[EFCore 5, SQLite3]: how to create table without ROWID[EFCore 5, SQLite3]:如何创建没有 ROWID 的表
【发布时间】:2021-02-27 07:09:46
【问题描述】:
我有一个具有非整数主键的模型。 TEXT 不能是 ROWID 的别名,sqlite 会自动创建一个 ROWID 列。
我可以在手动制定方案时禁用 ROWID,但在 EF 中我不知道该怎么做。
EF 像这样创建表:
CREATE TABLE text_data (
id TEXT NOT NULL PRIMARY KEY,
text TEXT NOT NULL
);
但我希望表格是这样的:
CREATE TABLE text_data (
id TEXT NOT NULL PRIMARY KEY,
text TEXT NOT NULL
) WITHOUT ROWID;
我可以告诉 EF 禁用 ROWID 什么?
【问题讨论】:
标签:
c#
sqlite
entity-framework-core
rowid
【解决方案1】:
public class MyRelationalCommandBuilder : RelationalCommandBuilder
{
static readonly String _beginCreateTable = "CREATE TABLE";
static readonly String _endCreateTable = ");";
static readonly String _withoutRowId = ") WITHOUT ROWID;";
public MyRelationalCommandBuilder(RelationalCommandBuilderDependencies dependencies) : base(dependencies)
{
}
public override IRelationalCommand Build() => new RelationalCommand(Dependencies, _fixCreateTableCommand(), Parameters);
String _fixCreateTableCommand()
{
String originalCommandText = base.ToString();
Int32 startCreateTableIndex = originalCommandText.IndexOf(_beginCreateTable);
if (startCreateTableIndex < 0 || originalCommandText.Contains(_withoutRowId) || originalCommandText.Contains("AUTOINCREMENT"))
return originalCommandText;
Int32 endCreateTableIndex = originalCommandText.IndexOf(_endCreateTable, startCreateTableIndex);
String createTableSubstring = originalCommandText.Substring(startCreateTableIndex, endCreateTableIndex - startCreateTableIndex + _endCreateTable.Length);
String newCreateTableSubstring = createTableSubstring.Replace(_endCreateTable, _withoutRowId);
String newCommandText = originalCommandText.Replace(createTableSubstring, newCreateTableSubstring);
return newCommandText;
}
}
public class MyRelationalCommandBuilderFactory : RelationalCommandBuilderFactory
{
public MyRelationalCommandBuilderFactory(RelationalCommandBuilderDependencies dependencies) : base(dependencies)
{
}
public override IRelationalCommandBuilder Create() => new LsRelationalCommandBuilder(Dependencies);
}
public class MyDbContext : DbContext
{
protected void OnConfiguring(DbContextOptionsBuilder optionsBuilder, String dbFilePath)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder
.UseSqlite()
.ReplaceService<IRelationalCommandBuilderFactory, MyRelationalCommandBuilderFactory>();
}
}