【问题标题】:Upgrade from EF 4 to 6, class inheritence and Discriminator从 EF 4 升级到 6,类继承和鉴别器
【发布时间】:2016-01-27 17:01:26
【问题描述】:

我有一个 EF 4 解决方案,我正在尝试迁移到更新的 EF(和 .net) 我已经升级了 EF 并修复了所有项目,以便处理 EF 6 和新的目标平台。 问题是 EF4 和 6 以不同的方式处理 db 中的类继承。我有一个继承 User 类的 BackendUser 类。在 db 中,BackendUser 表将具有 BackendUser 属性和一个将获取用户属性的 UserId

升级 EF 时会尝试从 User 表中获取所有数据并使用 Discriminator 属性来处理类。

我猜我必须要么将 db 转换为新方式,要么将 EF 设置为以“旧”方式处理继承。我也猜测新方法的性能可能会更好?

是否有任何最佳实践如何处理此问题以获取新数据库结构的旧解决方案,或者我是否正在花费数小时手动更新数据库?

编辑:找到有关 TPT 和添加类的更多信息,所以我猜 EF 出于某种原因不处理表属性? (省略了一些道具)

[Table("ResellerContact")]
public class ResellerContact : BackendUser
{        
    public string ResellerName {get; set; }
}

[Table("BackendUser")]
public class BackendUser : User
{
    public bool IsSystemOwner { get; set;}     
}

public abstract class User 
{
    public long UserId { get; set; }

    [Required(ErrorMessage = "*")]
    [StringLength(15, ErrorMessageResourceName = "UsernameValidationMessage", ErrorMessageResourceType = typeof(UserResource))]
    [Display(Name = "Username", ResourceType = typeof(ResellerContactResource))]
    public string UserName { get; set;}
}

在下面的sql中获取一个后端用户结果

SELECT TOP (2) 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[UserId] AS [UserId], 
[Extent1].[UserName] AS [UserName], 
[Extent1].[Email] AS [Email], 
[Extent1].[Password] AS [Password], 
[Extent1].[RoleId] AS [RoleId], 
[Extent1].[IsSystemOwner] AS [IsSystemOwner], 
[Extent1].[FullName] AS [FullName], 
[Extent1].[Phone1] AS [Phone1], 
[Extent1].[Mobile1] AS [Mobile1], 
[Extent1].[ResellerContactType] AS [ResellerContactType], 
[Extent1].[Language1] AS [Language1], 
[Extent1].[ResellerId] AS [ResellerId], 
[Extent1].[IsActive1] AS [IsActive1]
FROM [dbo].[User] AS [Extent1]
WHERE ([Extent1].[Discriminator] IN (N'ResellerContact',N'BackendUser')) AND ([Extent1].[UserName] = @p__linq__0) AND ([Extent1].[Password] = @p__linq__1)

【问题讨论】:

    标签: c# entity-framework inheritance


    【解决方案1】:

    我已经做了一些测试,这应该可以使用 Table 属性

    public class FooContext : DbContext
    {
       public DbSet<User> Users { get; set; }
       public DbSet<BackendUser> BackendUsers { get; set; }
       public DbSet<ResellerContact> ResellerContacts { get; set; }
    }
    

    这是生成的迁移代码,它是 TPT,应该与您的数据库匹配:

    CreateTable(
        "dbo.Users",
        c => new
            {
                UserId = c.Long(nullable: false, identity: true),
                UserName = c.String(),
            })
        .PrimaryKey(t => t.UserId);
    
    CreateTable(
        "dbo.BackendUser",
        c => new
            {
                UserId = c.Long(nullable: false),
                IsSystemOwner = c.Boolean(nullable: false),
            })
        .PrimaryKey(t => t.UserId)
        .ForeignKey("dbo.Users", t => t.UserId)
        .Index(t => t.UserId);
    
    CreateTable(
        "dbo.ResellerContact",
        c => new
            {
                UserId = c.Long(nullable: false),
                ResellerName = c.String(),
            })
        .PrimaryKey(t => t.UserId)
        .ForeignKey("dbo.BackendUser", t => t.UserId)
        .Index(t => t.UserId);
    

    【讨论】:

    • TPC 将在所有表中创建所有数据库文件。 db 是使用 EF4 生成的,现在我的所有语法都相同。原始是 TPT,其中 BackendUser 有一个 UserId,所有用户数据都存储在用户表中。 EF6 尝试使用属性进行 TPH
    • 哦,我明白了,抱歉,问题理解错了。如果你想要TPTTable 属性应该可以工作,但你需要在DbContext 中使用一个DbSet&lt;User&gt;
    • 我有一些类的通用存储库,BackendUser 就是其中之一。当错误引发是 Context.Set().SingleOrDefault(t => t.username = username) 时我会做什么。它在升级前工作,但现在它将使用鉴别器 instread。
    • @Trixz 看到我的编辑,这应该可以工作,请测试它并告诉我它是如何进行的
    • 我实际上做了一个简单的测试,它也适用于Table 属性(我已经重新编辑)。只需添加一组User,沿着两个继承的
    【解决方案2】:

    解决了问题,是实体框架版本。

    我更新了实体框架,解决了一些关于 System.ComponentModel.DataAnnotations(与其他人)的参考问题,然后将 taget 版本更改为 .Net 4.6

    然后我发现链接表明 Entity Framework 需要为新目标重新安装并且没有从所有项目中删除。所以当我安装它时,它一直在为 .Net 4.0 安装

    所以,在所有项目上卸载 Entity Framework,再次添加它,这样目标就会正确并且 [Table] 仍然有效。我猜注释属性来自错误的库,并且没有被实体框架正确处理。

    参考:Can I implement Entity Framework 5 TPT on Windows XP?

    TPT 仍然是一个性能问题(https://msdn.microsoft.com/en-US/data/hh949853 中的第 7.2 节),我将尝试将其更改为 TPH。为了解决这个问题,我发现我将为我当前的数据库创建一个迁移,然后对类进行重构以获取迁移脚本如何更新表。 该线程将我指向了那个方向 Entity Framework Code First Convert TPT to TPH

    感谢@Jcl 的输入

    【讨论】:

      猜你喜欢
      • 2013-10-30
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      相关资源
      最近更新 更多