内存中的 EF Core SQLite 异常:SQLite 错误 1:“接近“MAX”:语法错误”

Dei*_*kis 5 c# sqlite entity-framework-core ef-core-2.0 ef-core-2.1

我正在为单元测试创​​建 SQLite In Memory 数据库:

        var connection = new SqliteConnection("DataSource=:memory:");
        connection.Open();

        try
        {
            var options = new DbContextOptionsBuilder<BloggingContext>()
                .UseSqlite(connection)
                .Options;

            // Create the schema in the database
            using (var context = new BloggingContext(options))
            {
                context.Database.EnsureCreated();
            }

            // Run the test against one instance of the context
            using (var context = new BloggingContext(options))
            {
                var service = new BlogService(context);
                service.Add("http://sample.com");
            }

            // Use a separate instance of the context to verify correct data was saved to database
            using (var context = new BloggingContext(options))
            {
                Assert.AreEqual(1, context.Blogs.Count());
                Assert.AreEqual("http://sample.com", context.Blogs.Single().Url);
            }
        }
Run Code Online (Sandbox Code Playgroud)

context.Database.EnsureCreated(); 失败并出现异常: 消息:Microsoft.Data.Sqlite.SqliteException:SQLite 错误 1:“接近“MAX”:语法错误。

github 问题说: 这里的问题是 varchar(max) 是 SqlServer 特定类型。脚手架不应将其添加为在其他提供程序中传递给迁移的关系类型,这在迁移时容易生成无效的 sql。

但是,如果我的数据库包含许多 varchar(max) 列,那么如何在内存中使用 SQLite 进行单元测试?

Pre*_*Fan 0

我没有找到直接的解决方案,但已开始使用配置文件解决方法。您没有表明您是否正在使用 EF 配置,因此如果不需要,请忽略基础知识。

在您的 DbContext 中放置以下内容:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfigurationsFromAssembly(typeof(ChildrensSsiContext).Assembly);
}
Run Code Online (Sandbox Code Playgroud)

现在创建一个静态类,如下所示。它将获取您的财产并处理配置。

internal static class ConfigurationHelper
{
    internal static void ConfigureVarcharMax(PropertyBuilder<string> propertyBuilder, bool isRequired = true)
    {
        propertyBuilder
            .IsRequired(isRequired)
            //.HasColumnType("varchar(max)");
            .HasColumnType("text");
    }
}
Run Code Online (Sandbox Code Playgroud)

为每个要配置的实体创建一个配置类

public class MyEntityWithVarcharMaxConfiguration
    : IEntityTypeConfiguration<MyEntityWithVarcharMax>
{
    public void Configure(EntityTypeBuilder<MyEntityWithVarcharMax> builder)
    {
        ConfigurationHelper.ConfigureVarcharMax(builder.Property(e => e.MyVarcharMaxProperty));
    }
}
Run Code Online (Sandbox Code Playgroud)

保留 HasColumnType("text") 未注释以进行测试。然后在添加迁移时注释该行并取消注释 HasColumnType("varchar(max)")。

您需要记住这样做很痛苦,但这是一个相当简单的解决方法。