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



我正在使用一个使用 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.

也许首先使用模型无法做到这一点,我需要先切换到代码?

您可以引入一个接口,并将其添加到每个实体的分部类文件中。 但是,若要进行类继承,可能需要从现有数据库切换到"代码优先"。 顺便说一句,最终你可能不得不从现有数据库切换到代码优先,因为它更好,并且受 EF Core 支持。

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

我看到两种方法: 这两种方法我都不称完美,但也许它会有所帮助或改进:

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

最新更新