Entity Framework是否支持模型中不同的数据类型?

6

我考虑使用EF访问安装在客户系统上的遗留SQL Server数据库。

问题在于,这些数据库架构不是100%一致:虽然它们都有相同的(相关)表和字段,但某些数字字段可能具有不同的数据类型。

就应用程序而言,据我所见,这些类型是“兼容”的:例如,客户A数据库中包含小数字的字段可能是smallint,但客户B数据库中是一个int,或者包含价格的字段在A的数据库中可能是decimal(10,2),但在B的数据库中是float(是的,这意味着B可能会出现浮点问题 - 毕竟这是一个遗留数据库)。

由于我们不是唯一访问数据库的人,因此更改(并且统一)架构不是一种选择。 Entity Framework能够处理这种情况吗(即,如果模型定义声称是decimal(10,2),那么它是否能够优雅地接受SQL Server表中的double),还是它会崩溃艰难?


1
你尝试过这样的测试吗:将同一模型指向几个具有不同之处的测试数据库?请记住,数据可能会产生影响(例如,没有小数部分的十进制值可能有效,而带有小数部分的值可能失败)。 - Richard
2
@Richard:还没有,如果没有人能提供权威的答案,我计划这样做。如果我测试它并且它能够工作,我仍然不知道它是否“应该这样工作”,或者它“只是由于EF的某些实现细节巧合地正常工作”。 - Heinzi
确实,“似乎可以工作”的结果不会是确定的(但在这里你也不会得到)。然而,“无法工作”的结果则是确定的。因此,您将能够提出真正的问题:在这些情况下如何适应/使用EF(考虑到不太可能自动支持所有可想象的映射,您需要那个问题,无论“官方”立场如何)。 - Richard
3个回答

4
如果您在StackOverflow上查看,您会发现许多问题询问如何将数据库中的一种数据类型映射到另一种数据类型: 将Short映射为Bool 将'Y'/'N'映射为true/false在Entity Framework 4.1中将从数据库转换为字符串的内容转换为布尔属性 将time(0)映射为DateTime 几乎总是解决方案是在实体中有两个字段,并编写代码进行显式转换。
少数数据类型可以使用FluentAPI进行映射,并且您可以使用自定义代码优先约定。

datetime2转换为DateTime

你的smallint转换为int将属于此类别,但我很确定float转换为decimal(10, 2)不会。

由于有多个具有不同数据类型的数据库,因此我认为仅使用EF本身无法很好地工作。

我能想到两件事情:

在每个数据库中创建视图以一致地映射数据类型,然后从视图反向工程实体框架。您还可能必须将CUD映射到存储过程,然后修改每个数据库的创建和更新SQL以转换数据类型。

或者

查看Dapper,您可以更好地控制sql并在那里进行转换。这个答案中有关于仓储模式的混合实现的链接EF + Dapper混合实现


1
Entity Framework 能够处理这个问题吗(即,如果模型定义声称是 decimal(10,2),那么它是否会优雅地接受 SQL Server 表中的 double),还是会崩溃得很惨?我认为这不会引起问题,因为实体框架在执行查询之前进行所有必要的转换,并且由于从浮点数到十进制数没有隐式转换,所以您应该在编译时检测到它并进行显式转换。

1

这是对问题的非常晚回答,但我们刚刚遇到了与OP完全相同的问题 - 一个客户端将某些字段定义为int,而另一个客户端将这些字段定义为bigint。如果此解决方案已经存在其他地方,请原谅 - 我查找了但没有找到。

这可能不是最漂亮的解决方案,但在问题不是普遍存在的情况下,它可以很好地工作(这将证明需要单独的数据库上下文)。在我们的情况下,出现了一个单独的表格问题,并且更改数据库中的类型是一个较不优选的选项(风险、部署限制、客户依赖)。

首先为同一张表创建客户端特定的实体:

[Table("DbTableName")]
public class EntityForClientA
{
    public long Id { get; set; }
    public long GroupId { get; set; }
    //Alongside fields that don't differ
}

[Table("DbTableName")]
public class EntityForClientB
{
    public int Id { get; set; }
    public int GroupId { get; set; }
    //Alongside fields that don't differ
}

然后在数据源中:

    public DbSet<EntityForClientA> EntitiesA { get; set; }
    public DbSet<EntityForClientB> EntitiesB { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        if (isClientA) modelBuilder.Ignore<EntityForClientB>();
        else modelBuilder.Ignore<EntityForClientA>();
        base.OnModelCreating(modelBuilder);
    }

从那里,我们创建适用于所服务的客户的正确实体的商业模型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接