为现有的实体框架工作实体创建基本类型(EF模型优先)

时间:2018-10-15 22:15:24

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

我正在使用使用EF设计器和.edmx文件(第一个模型)的Entity Framework项目。实体映射到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实体成为其固有对象,但是由于不需要{{1}映射到数据库中的任何内容。我只想创建可以只读方式处理三种资源类型中的任何一种的代码。我不需要创建新的GenericResource

也许首先使用模型是不可能的,我需要先转换为代码吗?

2 个答案:

答案 0 :(得分:2)

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

在代码中,首先,如果您希望数据库忽略基类,则只需将其从DbContext中排除。您将可以在整个代码库中替换子类的实例,但是将没有一个可以查询的DbSet。

答案 1 :(得分:1)

我看到了两种方法:我都不会称之为完美的方法,但也许会有所帮助或有一个改进的想法:

1)将数据库更改为具有资源表,以便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也不会覆盖它们。