实体框架7创建不需要的备用密钥

时间:2016-01-28 19:05:50

标签: c# entity-framework

我有两个使用Entity Framework 7的简单类,一切都在所有类上正常工作,除了一个实例框架生成一个与现有列同名的新备用密钥的情况。

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])
);

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

关于下一个显而易见的问题,我们将如何管理引用,整体结构和接口的设计方式应该得到解决。无论如何,讨论将超出当前问题的范围。

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

  

ArgumentNullException:值不能为null。参数名称:type

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

问题在于您说InvoiceItem有一个带有外键的引用(Invoice)(InvoiceID,类型为string)。

然而,ID的{​​{1}}是Invoice,而不是long,因此它会使用自己的字符串键来符合您的要求。

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