【问题标题】:Entity Framework 7 creates an unneeded alternate keyEntity Framework 7 创建一个不需要的备用键
【发布时间】:2016-01-28 19:05:49
【问题描述】:

我有两个使用 Entity Framework 7 的简单类,在所有类上一切正常,除了 Entity Framework 生成与现有列同名的新备用键的情况。

Invoice.cs

namespace Arinsys.Accounts
{
    [Table(name: "Invoice", Schema = "Arinsys_Accounts")]
    public class Invoice
    {
        public long ID { get; set; }
        public string InvoiceID { get; set; }
        public long? CustomerUID { get; set; }
        public long? EmployeeUID { get; set; }
        public DateTime BillDateTime { get; set; }
        public long Amount { get; set; }
        public long? Discount { get; set; }
        public string DiscountReason { get; set; }
        public string CouponID { get; set; }
        public long Charges { get; set; }
        public string ChargesReason { get; set; }
        public long Tax { get; set; }
        public string TaxType { get; set; }
        public long FinalAmount { get; set; }
        public string Status { get; set; }
        public string Remarks { get; set; }

        [ForeignKey("CustomerUID")]
        public virtual CRM.User Customer { get; set; }
        [ForeignKey("EmployeeUID")]
        public virtual CRM.User BilledBy { get; set; }

        public virtual ICollection<InvoiceItems> Items { get; set; }
        public virtual ICollection<Payments> Payments { get; set; }
    }
}

生成的发票表代码

CREATE TABLE [Arinsys_Accounts].[Invoice] (
    [ID]             BIGINT         IDENTITY (1, 1) NOT NULL,
    [Amount]         BIGINT         NOT NULL,
    [BillDateTime]   DATETIME2 (7)  NOT NULL,
    [Charges]        BIGINT         NOT NULL,
    [ChargesReason]  NVARCHAR (MAX) NULL,
    [CouponID]       NVARCHAR (MAX) NULL,
    [CustomerUID]    BIGINT         NULL,
    [Discount]       BIGINT         NULL,
    [DiscountReason] NVARCHAR (MAX) NULL,
    [EmployeeUID]    BIGINT         NULL,
    [FinalAmount]    BIGINT         NOT NULL,
    [InvoiceID]      NVARCHAR (MAX) NOT NULL,
    [InvoiceID1]     NVARCHAR (450) NOT NULL,
    [Remarks]        NVARCHAR (MAX) NULL,
    [Status]         NVARCHAR (MAX) NULL,
    [Tax]            BIGINT         NOT NULL,
    [TaxType]        NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_Invoice] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [AK_Invoice_InvoiceID1] UNIQUE NONCLUSTERED ([InvoiceID1] ASC),
    CONSTRAINT [FK_Invoice_User_CustomerUID] FOREIGN KEY ([CustomerUID]) REFERENCES [Arinsys_CRM].[User] ([ID]),
    CONSTRAINT [FK_Invoice_User_EmployeeUID] FOREIGN KEY ([EmployeeUID]) REFERENCES [Arinsys_CRM].[User] ([ID])
);

InvoiceItems.cs

namespace Arinsys.Accounts
{
    [Table(name: "InvoiceItems",Schema = "Arinsys_Accounts")]
    public class InvoiceItems
    {
        public long ID { get; set; }
        public string InvoiceID { get; set; }
        public string ItemID { get; set; }
        public int Quantity { get; set; }
        public int Price { get; set; }
        public int Discount { get; set; }
        public string Reason { get; set; }
        public int Amount { get; set; }
        public string Remarks { get; set; }

        [ForeignKey("InvoiceID")]
        public virtual Invoice Invoice { get; set; }

    }
}

生成的 InvoiceItems 表代码

CREATE TABLE [Arinsys_Accounts].[InvoiceItems] (
    [ID]        BIGINT         IDENTITY (1, 1) NOT NULL,
    [Amount]    INT            NOT NULL,
    [Discount]  INT            NOT NULL,
    [InvoiceID] NVARCHAR (450) NULL,
    [ItemID]    NVARCHAR (MAX) NULL,
    [Price]     INT            NOT NULL,
    [Quantity]  INT            NOT NULL,
    [Reason]    NVARCHAR (MAX) NULL,
    [Remarks]   NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_InvoiceItems] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_InvoiceItems_Invoice_InvoiceID] FOREIGN KEY ([InvoiceID]) REFERENCES [Arinsys_Accounts].[Invoice] ([InvoiceID1])
);

注意 Invoice Table 中的 InvoiceID1 列,它是自动创建的,我不需要它。由于这些模型在库中,即它们就像模板一样,实际的 dbcontext 将在应用程序中,我不希望最终开发人员担心这些事情,所以流畅的 API 在 OnModelCreating 不是一个选项。

至于下一个明显的问题,我们将如何管理引用,整体结构和界面的设计方式使其得到照顾。无论如何,讨论将超出当前问题的范围。

我同意,我可以在 InvoiceItems 表中看到外键设置为 InvoiceID1,但我希望它链接到 Invoice 表中的 ID 列,如果我添加一个 [InverseProperty("ID")] 属性以及现有的 [ForeignKey ("InvoiceID")] InvoiceItems 类中 Invoice 对象的属性出现错误

ArgumentNullException:值不能为空。参数名称:类型

在撰写本文时,Entity Framework 仍然很新,文档仍然不完整,Stackoverflow 和其他地方的所有答案都说明了如何做到这一点的答案,即如何创建备用/唯一键,但不幸的是我找不到任何答案如何防止它。

编辑:虽然这个问题是我的编程错误,正如@Jcl 回答的那样,但我们已经收到了一些很好的答案,例如@Steve Greene 发布了关于 EF SQL 中的字符串长度限制,这可能对未来的读者有所帮助,所以我将问题保留原样

【问题讨论】:

  • 请也发布您的 InvoiceItems 课程。
  • “模型在库中”是什么意思?为什么这会阻止您使用 Fluent API?
  • 他使用的是 EF Core 1.0。文档可能不如 EF6 强大
  • @jvanrhyn Ahh 所以他的意思是 EF 7,而不是一般的 EF。知道了。谢谢。
  • @DStanley“模型在库中”意味着它们只是模板,我已经更新了问题以提高清晰度

标签: c# entity-framework


【解决方案1】:

问题是你说你的InvoiceItem 有一个引用(Invoice),它有一个外键(InvoiceID,它的类型是string)。

但是InvoiceIDlong,而不是string,因此它会根据您的要求制作自己的字符串键。

我的猜测:如果您将 InvoiceItem 中的 public string InvoiceID { get; set; } 更改为:public long InvoiceID { get; set; } 它应该会停止创建密钥,而且您实际上会得到正确的外键。

【讨论】:

  • 谢谢,它确实解决了问题,傻我,我忽略了这么简单的事情。 :(
  • 树木的森林。
【解决方案2】:

EF(SQL) 无法索引超过 900 个字节(450 个 unicode)的字符串,因此它会为您创建一个。将您的模型更改为:

[StringLength(450)]
public string InvoiceID { get; set; }

或者使用类似的流畅命令来限制它。 Entity Framework code first unique column

【讨论】:

  • 这是我今天学到的一个有趣的新东西,但是它没有解决我的问题@Jcl 答案是正确的答案,我忽略了类型,这正是指定错误消息时所说的逆属性,但这个答案肯定值得一票,所以+1
猜你喜欢
  • 2020-10-18
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 2020-08-10
  • 2015-01-15
相关资源
最近更新 更多