gpt4 book ai didi

c# - 在 Entity Framework 和 Sql Server 中创建对象计数器

转载 作者:行者123 更新时间:2023-11-30 23:28:49 24 4
gpt4 key购买 nike

注意 1:我改写了问题。它现在由供应商和订单组成,而不是汽车和零件。

注意 2:此问题是假设性的。我的目标是了解如何创建对象计数器。

为了监管要求,我需要为每个供应商的每个订单依次编号。

我在 SQL Server 中使用 'Entity Framework`

在我的假设示例中,我有一个Supplier 类和一个Order 类。

每个供应商都有订单。每个订单都有一个产品和一个数量。意思是,它说明了从供应商处订购了哪种产品以及订购了多少。

我需要能够创建计数器(例如自动递增的数字)来计算每个供应商的订单。

出于监管原因,每个供应商都必须按创建顺序对其订单进行顺序编号,并且只能使用整数。

当我们检查一个 Order 时,我们应该通过它的 OrderCountForSupplier 列知道它的创建顺序是什么(DateTime/TimeStamp 列监管部门是不够的。他们需要这样一个柜台)。

为简单起见,无法删除订单(它的状态可以更改,但无法删除)。

对我来说,拥有一个包括技术/编程方式的解决方案非常重要,而不仅仅是理论上的方式。

我画了一张图,以便以最清楚的方式解释我的问题:

enter image description here


我有一个可行的方法,很高兴听到反馈。

我正在考虑一个/多个外部表来保存计数器。像这样的东西:

Supplier Order Counters Table

| SupplierId | OrderCountForSupplier
------------------------
| 54654 | 3
| 78787 | 2
| 99666 | 4

我是否需要触发器才能在每次插入时为每个供应商递增 OrderCountForSupplier 计数器?

如果不是 - 如何以安全的方式完成这个增量? (例如,没有两个处于竞争状态的进程来获取下一个计数器并递增它,这最终可能导致重复的订单计数)。

还有一条注意事项:这可以通过 Entity Framework 明智地完成吗?如果不是 - 将采用 Sql Server 解决方案。

最佳答案

第一个回答,题中的例子写完后变了。

您说零件 I​​D 中有间隙是可以的,因为“某些零件可能会在途中被删除”。

那么,你的例子有什么区别:

Car      PartID
54654 1
54654 2
54654 3
78787 1
78787 2
99666 1
99666 2
99666 5
99666 7

这个变体:

Car      PartID
54654 1
54654 2
54654 3
78787 4
78787 5
99666 6
99666 7
99666 8
99666 9

在第二个变体中,每个零件都有一些 ID,对于每辆车来说都是唯一的(它在全局范围内也是唯一的,但这并不重要)。在第二个变体中,PartID 指定零件插入表中的顺序,与第一个变体相同。

因此,我将使用一个简单的 IDENTITY 列:

零件

PartID int IDENTITY NOT NULL (PRIMARY KEY)
CarLicenseNum int NOT NULL (FOREIGN KEY)
PartName varchar(255)

更新供应商订单示例

更新后的问题中最重要的一点是“监管原因”。它回答了你为什么要做这种不自然的事情的问题。 “监管”与效率往往是对立的。

本质上,这意味着你必须使用 serializable transaction isolation level在插入新行并计算序列中的下一个数字时。它会损害并发/吞吐量,但它会保证多用户环境中的一致性和“安全”。

Entity Framework 中不知道怎么做,应该可以吧。但是,同样,出于“监管原因”,我将把这个逻辑放在数据库的存储过程中,并确保普通用户没有直接对 Orders 表的写访问权限,但有权限只执行这个专用的存储过程。您可以在 EF 代码中复制此存储过程的逻辑,但数据库本身将对通过其他应用程序所做的更改开放,这可能不符合法规要求。

您可以使用单独的表来实现它,该表存储每个供应商的最新序列号,或者您可以即时读取最后一个最大序列号。如果每个供应商只有很少的订单,那么这个包含最新计数器值的单独表将与 Orders 表相当,您不会有太多收获。无论如何,拥有合适的索引是关键。获取最新的计数器值将是索引中的一个搜索。

这是一个不使用额外表的存储过程示例。

确保 Orders 表在 (SupplierId, OrderCountForSupplier) 上具有唯一索引。事实上,即使您使用额外的表来强制执行约束,您也必须具有此索引。

CREATE PROCEDURE [dbo].[AddOrder]
@ParamSupplierID int,
@ParamProductSerial varchar(10),
@ParamQuantity int,
@NewOrderID int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;
BEGIN TRY

DECLARE @VarMaxCounter int;

SELECT TOP(1) @VarMaxCounter = OrderCountForSupplier
FROM dbo.Orders
WHERE SupplierID = @ParamSupplierID
ORDER BY OrderCountForSupplier DESC;

SET @VarMaxCounter = ISNULL(@VarMaxCounter, 0) + 1;

INSERT INTO dbo.Orders
(SupplierID
,OrderCountForSupplier
,ProductSerial
,Quantity)
VALUES
(@ParamSupplierID
,@VarMaxCounter
,@ParamProductSerial
,@ParamQuantity);

SET @NewOrderID = SCOPE_IDENTITY();

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- TODO: handle the error
SET @NewOrderID = 0;
ROLLBACK TRANSACTION;
END CATCH;

END
GO

关于c# - 在 Entity Framework 和 Sql Server 中创建对象计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35825947/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com