0

我有一个Organisation代表企业的实体,它可以是供应商客户两者兼而有之

实体如下所示:

public abstract class Organisation
{
    public Organisation()
    {
        IsCustomer = false;
        IsSupplier = false;
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public bool IsSupplier { get; set; }
    public bool IsCustomer { get; set; }
}

我创建了称为组织的子类,Customer因为Supplier这将使Organisations在我的域的其他部分工作时更容易(例如Organisation,只有一个Supplier可以与采购订单相关联)。

我创建了两个派生自该类的Organisation类。

public class Supplier : Organisation
{
}

public class Customer : Organisation
{
}

接下来我想告诉 Entity Framework 如何将这些类映射到表中。所有信息都将存储在一个名为“组织”的表中,因此我尝试使用 TPH(每层级表)映射。

这是我希望我的映射工作的方式:

  • 如果我查询Organisations,我希望实体框架返回所有组织,而不管IsCustomerIsSupplier属性中的值如何。
  • 如果我查询Suppliers,我希望 Entity Framework 返回所有组织所在的位置IsSupplier = true
  • 如果我查询Customers,我希望 Entity Framework 返回所有组织所在的位置IsCustomer = true

一个组织既是客户又是供应商是有效的,所以我希望一些组织同时包含在CustomerSupplier查询中。

这是我定义的配置类:

class OrganisationConfiguration : EntityTypeConfiguration<Organisation>
{
    internal OrganisationConfiguration()
    {
        ToTable("Organisations");
        HasKey(o => o.Id);

        Map<Customer>(m =>
            {
                m.Requires("IsCustomer").HasValue(true);
            });

        Map<Supplier>(m =>
            {
                m.Requires("IsSupplier").HasValue(true);
            });
    }
}

这会导致DataException抛出以下消息:

错误 3032:从第 59 行开始映射片段时出现问题:条件成员 'Organisation.IsSupplier' 的条件不是 'IsNull=False' 被映射。删除 Organisation.IsSupplier 上的条件或将其从映射中删除。

我不确定如何修复此错误,或者即使我想做的事情是可能的,因为我看到的所有示例都有一个鉴别器列。尽管我需要区分既是客户又是供应商的组织,但我不确定我是否能够使用单个鉴别器实现我想要的结果。

更新:

经过一些研究,错误似乎是我在课堂上定义了IsSupplierandIsCustomer属性的结果。Organisation如果我删除这些属性,那么我的数据库将正确构建并且我的映射工作(实体框架在我的表中创建单独的鉴别器)。

我已经用 3 个单独的查询(1 到 select Organisations,1 到 selectCustomers和 1 到 select Suppliers)对此进行了测试,这似乎让我得到了正确的结果,所以这让我大约 90% 的方式接近我的解决方案。

我现在遇到的问题是我需要一种方法来Customer从数据库中选择一个并且还设置为供应商(因为我没有要设置的属性)。

4

1 回答 1

1

现在无法尝试,但我认为只允许使用 1 个鉴别器列。

public abstract class Organisation
{
    ...
    //public bool IsSupplier { get; set; }
    //public bool IsCustomer { get; set; }
    public int SubType { get; set; }
}

   Map<Customer>(m =>
        {
            m.Requires("SubType").HasValue<int>(1);
        });

   Map<Supplier>(m =>
        {
            m.Requires("SubType").HasValue<int>(2);
        });

您当然应该定义一个枚举来替换 int。


你已经想通了,但是

一个组织既是客户又是供应商是有效的
……
因为我需要区分既是客户又是供应商的组织。

这完全违背了这里的基本 OOP 原则。一个实例不能是 2 个派生类型,这在 C# 中不受支持。

如果你想实现这个,你需要一个完全不同的设计。


我需要一种从数据库中选择客户并且还设置为客户的方法(因为我没有要设置的属性)。

您可以使用以下方法选择客户或供应商OfType<>

 IEnumerable<Customer> allCustomers = myContext.Organisations.OfType<Customer>();

您可以简单地将客户添加到公共实体集中:

var c = new Customer(....);
myContext.Organisations.Add(c);

通常,您不会在查询中使用鉴别器属性。

于 2013-05-07T12:59:26.927 回答