所以我有一张发票的表格。目前,Key列用作发票号。它会自动递增,因为它是一个关键列。
现在该应用程序将被不同国家的不同公司使用。因此,如果两者都创建发票,则发票编号不正确。
因此,在国家A中,最新发票编号可能是2018002345,在国家B中,某人应该能够创建Id 201800001及其后201800002的发票。
当然,默认[Key]
列不适用于此,我想?
除此之外,最好为它们添加前缀,因此前缀包含国家代码:NL20180002345和US2018000001。 (当前缀是唯一的时,也许可以使用Key列?)。 在完美的情况下,数字增加+1,但如果这非常困难,那么具有99%概率的解决方案是可接受的。
所以我正在寻找一种正确的方法来处理这种情况。它是一个现有的和生产中的应用程序,因此无法改变密钥列是不可能的,如果更改它们将需要迁移。
我想避免我首先要调用数据库来检索最后一个密钥,然后插入一个递增的密钥,这会产生问题但不会扩展。
使用代码优先迁移生成数据库。我更喜欢可以使用代码优先注释的解决方案。但是,有第二个项目使用数据库而没有实体框架,它正在使用Dapper。那么另一方面,MSSQL解决方案也可以很好用吗?
当前实体:
发票
public class Invoice
{
public int InvoiceId { get; set; }
public int ContactId { get; set; }
public int BillingAddressId { get; set; }
public int? OrderId { get; set; }
public int? RefundInvoiceId { get; set; }
public DateTime Date { get; set; }
//more properties
[Timestamp]
public byte[] Timestamp { get; set; }
public DateTime? PayDate { get; set; }
public PaymentStatusEnum PaymentStatus { get; set; }
[ForeignKey("BillingAddressId")]
public Address BillingAddress { get; set; }
}
因此它链接到一个地址,该地址链接到一个包含国家/地区代码的国家/地区。
地址
public class Address
{
public int addressId { get; set; }
public int countryId { get; set; }
//more properties
public bool validated { get; set; }
public AddressTypeEnum addressType { get; set; }
public Country Country { get; set; }
}
国家
public class Country
{
public int CountryId { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
public double Taxpercentage { get; set; }
public int CurrencyId { get; set; }
[ForeignKey("CurrencyId")]
public Currency Currency { get; set; }
}
答案 0 :(得分:2)
作为服务器端解决方案,您可以在发票表上使用insert trigger,并在触发器代码中配备字段值。您可以使用(sequence objects)生成数字,这两个国家可能有两个不同的序列可能适合您。您的发票ID字段可以是nvarchar字符串,因此您的触发器代码也可以应用国家/地区前缀。
然后,在客户端,使用DatabaseGenerated属性标记该字段,如下所示:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string InvoiceId { get; set; }
当您插入或更新该表时,它指示EF在同一个往返中获取列值(在触发器中创建)。
简化示例:
create table Invoice (
Id int not null primary key identity(1,1),
InvoiceId nvarchar(20),
CountryId int not null
-- etc.
)
CREATE SEQUENCE InvNo_US
START WITH 1000000
INCREMENT BY 1;
GO
CREATE TRIGGER TriInvoice_AI
ON Invoice AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare @id int, @country_id int, @seq bigint;
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
SELECT i.Id, i.CountryId from inserted i
ORDER BY i.Id;
open c;
fetch next from c into @id, @country_id;
while @@FETCH_STATUS = 0
begin
/* TODO: At this point you may use different sequence object depending on @country_id,
you may apply different country prefixed and maybe do other specific formatting to the InvoiceId
This example always just uses 'US' and doesn't take the @country_id in account at all. */
set @seq = NEXT VALUE FOR InvNo_US;
update Invoice set InvoiceId = 'US' + cast(@seq as nvarchar) where Id=@id;
fetch next from c into @id, @country_id;
end
close c;
deallocate c;
END
像这样测试:
insert into Invoice (CountryId) values (42);
select * from Invoice;