1

我有两个表,它们来自旧系统。这些表从两个单独的外部源定期更新,并且仅用作我的应用程序中查找数据的“只读”表:

送货地点

public partial class DeliverySite
{
    public string CustomerID { get; set; } // PK
    public string CustomerName { get; set; }
    public string DeliveryAddress { get; set; }
    public string BillingAddress { get; set; }
    //... fields removed for clarity.

    // Navigational Properties.
    public virtual ICollection<Item> Items { get; set; }
}

public class DeliverySiteMap : EntityTypeConfiguration<DeliverySite>
{
    public DeliverySiteMap()
    {
        // Primary Key
        this.HasKey(t => t.CustomerID);

        // Properties
        this.Property(t => t.CustomerID)
            .IsRequired()
            .HasMaxLength(50);

        this.Property(t => t.CustomerName)
            .IsRequired()
            .HasMaxLength(50);

        this.Property(t => t.DeliveryAddress)
            .IsRequired();

        this.Property(t => t.BillingAddress)
            .IsRequired();

        // Table & Column Mappings
        this.ToTable("DeliverySites");
        this.Property(t => t.CustomerID).HasColumnName("CustomerID");
        this.Property(t => t.CustomerName).HasColumnName("CustomerName");
        this.Property(t => t.DeliveryAddress).HasColumnName("DeliveryAddress");
        this.Property(t => t.BillingAddress).HasColumnName("BillingAddress");   
    }
}

项目

public partial class Item
{
    public string Item { get; set; }  // PK
    public string ItemDescription { get; set; }
    public decimal Brand { get; set; }
    public decimal Price { get; set; }
    public string CustomerID { get; set; }  // PK + FK
    //... fields removed for clarity.

    // Navigational Properties.
    public virtual DeliverySite DeliverySite { get; set; }
}

public class ItemMap : EntityTypeConfiguration<Item>
{
    public ItemMap()
    {
        // Primary Key
        this.HasKey(t => new { t.Item, t.CustomerID });

        // Properties
        this.Property(t => t.UserItem)
            .HasMaxLength(50);

        this.Property(t => t.UserItemDescription)
            .HasMaxLength(255);

        this.Property(t => t.CCItem)
            .IsRequired()
            .HasMaxLength(50);

        this.Property(t => t.CCItemDescription)
            .IsRequired()
            .HasMaxLength(255);

        this.Property(t => t.CustomerID)
            .HasMaxLength(50);

        // Table & Column Mappings
        this.ToTable("Items");
        this.Property(t => t.Item).HasColumnName("Item");
        this.Property(t => t.ItemDescription).HasColumnName("ItemDescription");
        this.Property(t => t.Brand).HasColumnName("Brand");
        this.Property(t => t.Price).HasColumnName("Price");
        this.Property(t => t.CustomerID).HasColumnName("CustomerID");
    }
}

鉴于这些表是独立更新的,可能为“DeliverySites”输入的“项目”不存在。

因此,我想建立一个可选的关系。(所以我可以在我的应用程序中使用导航属性,但这样我就不会阻止表格被独立更新。)

在我的范围内,我ItemMap : EntityTypeConfiguration<Item>尝试了以下方法:

this.HasOptional(x => x.DeliverySite)
    .WithMany(x => x.Items)
    .HasForeignKey(x => x.CustomerID)
    .WillCascadeOnDelete(false);

但我收到此错误:

System.Data.Entity.Edm.EdmAssociationType::多重性与关系“Item_DeliverySite”中角色“Item_DeliverySite_Target”中的引用约束冲突。因为从属角色中的所有属性都不可为空,所以主体角色的多重性必须为“1”。

我应该如何实现这种关系?

此外,如果我可以在不在数据库中添加任何 FK 约束的情况下做到这一点,那将是理想的。这可能吗?

4

3 回答 3

1

您很可能遇到此错误,因为Item.CustomerID是必需的。尽管您没有IsRequired()在映射中调用它,但它是必需的,因为它是复合主键的一部分......

this.HasKey(t => new { t.Item, t.CustomerID });

...并且因为复合键的每一列都不允许NULL在数据库中。因此EF想要映射

this.HasRequired(x => x.DeliverySite)
    .WithMany(x => x.Items)
    .HasForeignKey(x => x.CustomerID)
    .WillCascadeOnDelete(false);

对我来说,真正的问题似乎是您正在尝试使用 EF 创建关系和导航属性,其中数据库中没有真正的关系和外键约束。

如果Item.CustomerID可以在数据库中有一个值,该值在表中不作为行存在,则DeliverySites您不能使用HasRequired,因为如果您尝试Item使用 anInclude加载DeliverySiteEF 将创建一个INNER JOIN并且ItemsDeliverySite通过CustomerIDwon引用现有的根本不加载。所以,基本上你会得到错误的查询结果。另一方面,您不能使用可选映射(这将导致LEFT OUTER JOIN),因为CustomerID它是 PK 的一部分,它会导致您的异常。

老实说,对于您的旧数据库架构,我不会尝试在您的 EF 模型中引入导航属性和人为关系。如果您在一个查询中需要“相关” DeliverySites 和Items,我可能更愿意使用手动 LINQ 连接CustomerID作为普通标量属性来连接数据并将加载DeliverySite的 s 和Items 投影到专门的类(或匿名对象)中.

于 2013-06-13T15:20:26.830 回答
0

我相信如果您删除外键并制作它,这将起作用:

this.HasOptional(x => x.DeliverySite)
    .WithMany(x => x.Items);
于 2013-06-11T12:11:14.463 回答
0

我知道这不是您想要的答案,但恕我直言,您最好花时间制定一个确保遗留数据库完整性的解决方案。在 ORM 中寻找非规范化数据库的变通方法不仅是不好的做法,而且会让您的同行感到头疼并贬低您的产品。不确定数据是如何保留的,但您可以将项目保存在临时表中,并且仅在存在相应的交付站点时才添加到规范化表中。

于 2016-04-23T09:42:53.407 回答