【问题标题】:Create a base type for existing Entity Frame work entities (EF Model First)为现有实体框架实体创建基本类型(EF 模型优先)
【发布时间】:2018-10-16 07:06:34
【问题描述】:

我正在处理一个使用 EF 设计器和 .edmx 文件(模型优先)的实体框架项目。实体映射到 MySQL 数据库并生成模型代码。我有 3 个在逻辑上代表“资源”并共享一些但不是所有字段的实体。例如:

public partial class ResourceA {
    public int ID { get; set; }
    public long ProductID { get; set; }
    public string Path { get; set; }
}

public partial class ResourceB {
    public int ID { get; set; }
    public long ProductID { get; set; }
    public string Label { get; set; }
}

public partial class ResourceC {
    public int ID { get; set; }
    public long ProductID { get; set; }
    public bool Open { get; set; }
    public bool Replacement { get; set; }
}

这些实体中的每一个都映射到数据库中的一个表。

我有一个代码区域,我想在其中循环三种不同的资源类型。在那个循环中,我不需要访问 3 种实体类型之间不常见的属性。有没有一种方法可以做到这一点,而无需创建三个单独的循环,除了实体类型之外,所有代码都相同?

我尝试在 EF 设计器中创建一个 GenericResource 实体,然后使 ResourceX 实体固有它,但在映射时我感到困惑,因为我不需要 GenericResource 映射到数据库。我只想创建可以以只读方式处理三种资源类型中的任何一种的代码。我不需要创建新的GenericResource

也许这在模型优先的情况下是不可能的,我需要先切换到代码?

【问题讨论】:

    标签: c# entity-framework entity-framework-core


    【解决方案1】:

    您可以引入一个接口并将其添加到每个实体的部分类文件中。但是要拥有类继承,您可能必须从现有数据库切换到 Code First。顺便说一句,最终您可能不得不从现有数据库无论如何切换到 Code First,因为它更好,并且受 EF Core 支持。

    在 Code First 中,如果您希望数据库不了解基类,只需将其从 DbContext 中排除。您将能够在整个代码库中替换子类的实例,但不会有一个可以查询的 DbSet。

    【讨论】:

    • 在四处寻找和尝试不同的东西时,我开始怀疑切换到 Code First 可能是最理想的解决方案。看来我有新东西要学了!
    【解决方案2】:

    我看到了两种方法:我认为这两种方法都不是完美的,但也许它会有所帮助或改进的想法:

    1) 把数据库改成有Resource Table,这样ResourceA、B、C就可以有外键关系。然后,您的每个类将如下所示:

    public partial class ResourceA
        {
            public Resource Resource {get; set;}
            public string Path { get; set; }
        }
    

    您将拥有一个 EF 将创建的表,如下所示:

    public partial class Resource
    {
      public int ID {get; set;}
      public long ProductId { get; set; }
    }
    

    另一种选择: 作为部分类,您可以扩展类并使用接口实现它们:

    一个快速且略显肮脏的概念证明:

    public interface IResources
    {
        Resource GetResource();
    }
    
    public partial class ResourceA : IResources
    {
        public Resource GetResource()
        {
            return new Resource()
            {
                ID = ID,
                ProductID = ProductID
            };
        }
    
    
    }
    public partial class ResourceB : IResources
    {
        public Resource GetResource()
        {
            return new Resource()
            {
                ID = ID,
                ProductID = ProductID
            };
        }
    }
    public partial class ResourceC : IResources
    {
        public Resource GetResource()
        {
            return new Resource()
            {
                ID = ID,
                ProductID = ProductID
            };
        }
    }
    public class Resource
    {
        public int ID { get; set; }
        public long ProductID { get; set; }
    }
    
    //These are the "generated" EF partials
    public partial class ResourceA
    {
        public int ID { get; set; }
        public long ProductID { get; set; }
        public string Path { get; set; }
    }
    
    public partial class ResourceB
    {
        public int ID { get; set; }
        public long ProductID { get; set; }
        public string Label { get; set; }
    }
    
    public partial class ResourceC
    {
        public int ID { get; set; }
        public long ProductID { get; set; }
        public bool Open { get; set; }
        public bool Replacement { get; set; }
    }
    

    这对我来说实际上不在数据库中,所以我只是在控制台应用程序中模拟了它:

           var A = new ResourceA()
            {
                ID = 15,
                Path = @"C:\Path",
                ProductID = 15001
            };
            var B = new ResourceB()
            {
                ID = 16,
                ProductID = 166101,
                Label = "Ham"
            };
            var C = new ResourceC()
            {
                ID = 188,
                Open = true,
                ProductID = 900014,
                Replacement = false,
    
            };
    
            List<IResources> resources = new List<IResources>();
            resources.Add(A);
            resources.Add(B);
            resources.Add(C);
    
            foreach(var r in resources)
            {
                Console.WriteLine(r.GetResource().ID);
            }
    

    它有效,但我想说它可能并不理想。我将接口和其他类放在数据访问层的单独文件中,这样 EF 就不会覆盖它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多