简体   繁体   English

SQL Server事务-C#

[英]SQL Server Transactions — C#

I need a help. 我需要帮助。 Let me first explain the scenario with a small sample. 让我首先用一个小样本来解释这种情况。

Suppose I have a Students table with columns: 假设我有一个带有列的Students表:

Id int(PK)  
Name varchar(200)  
Marks1 int  
Marks2 int  
Marks3 int  
TotalMarks int  
IsTotalCalculated bit  
InProcess bit

This table has huge number of records. 该表具有大量记录。

Now, I want to calculate the TotalMarks of each student and update the TotalMarks column. 现在,我想计算每个学生的TotalMarks并更新TotalMarks列。

Now coming to my C# Console App I am calling to stored procedures: 现在进入我的C#控制台应用程序,我正在调用存储过程:

SP1 => I am fetching top two records at a time which has InProcess = 0 and IsTotalCalculated = 0, sets its InProcess = 1 and do the processing. SP1 =>我一次获取前两个记录,该记录的InProcess = 0和IsTotalCalculated = 0,设置其InProcess = 1并进行处理。 (Has a SELECT and UPDATE) (具有SELECT和UPDATE)

SP2 => Finally again update these two rows which updates its IsTotalCalculated = 1 and InProcess = 0 (UPDATE) SP2 =>最后再次更新这两行,以更新其IsTotalCalculated = 1和InProcess = 0(UPDATE)

Concern: My concern is as soon as I select the 2 rows for processing then any other Console App instance should not select these 2 rows for processing. 关注:我担心的是,一旦我选择2行进行处理,那么任何其他Console App实例都不应选择这2行进行处理。 What should I do? 我该怎么办?
Note: I have put the C# code of my two SPs in a TransactionBlock. 注意:我已经将两个SP的C#代码放在TransactionBlock中。

Thanks, 谢谢,

Justin Samuel 贾斯汀·塞缪尔(Justin Samuel)

Can't you just check in SP1 if InProcess = 1 and then if that is true ignore the rest until InProcess becomes 0 ? 您不能仅在InProcess = 1中检查SP1,然后在InProcess变为0时忽略其余部分吗?

The trick is to block any reads while you update InProcess to 1. This can be done with SET TRANSACTION ISOLATION LEVEL READ COMMITTED which specifies that statements (in your SP) cannot read data that has been modified but not committed by other transactions. 诀窍是在将InProcess更新为1时阻止任何读取。这可以通过SET TRANSACTION ISOLATION LEVEL READ COMMITTED来完成,该操作指定语句(在SP中)不能读取已被修改但未被其他事务提交的数据。

Hope this helps. 希望这可以帮助。

Why on earth do you want to do this in C# ?? 为什么要在C#中执行此操作? This is perfect for T-SQL! 这对于T-SQL是完美的!

 UPDATE 
     dbo.Students
 SET 
     TotalMarks = (some formula),
     IsTotalCalculated = 1
 WHERE 
     IsTotalCalulated = 0

One T-SQL statement and you're done, no worries about transaction scopes and shuffling loads of data back and forth....... 一条T-SQL语句就完成了,您无需担心事务作用域和来回拖曳的数据负载.......

OK, so if you must stick to your current approach - here's what you could do: 好的,因此,如果您必须坚持当前的方法,可以执行以下操作:

Concern: My concern is as soon as I select the 2 rows for processing then any other Console App instance should not select these 2 rows for processing. 关注:我担心的是,一旦我选择2行进行处理,那么任何其他Console App实例都不应选择这2行进行处理。 What should I do? 我该怎么办?

How about "hiding" the Students table, eg not allowing anyone access to it, and instead using a view on top of it, which only ever shows the rows that have InProcess = 0? 如何“隐藏” Students表,例如不允许任何人访问它,而是使用它上方的视图,该视图仅显示InProcess = 0的行?

CREATE VIEW dbo.StudentsView
AS
    SELECT (list of fields)
    FROM dbo.Students
    WHERE InProcess = 0

This way, any request to read students will always only read those not being processed right now. 这样,任何阅读学生的请求都将始终仅阅读当前未处理的那些请求。

I'm sure you have a reason for doing things the way you are, but if this is the actual table and not just a illustrative sample then why don't you use a view with a calculated Total column? 我确定您有按自己的方式做事的理由,但是如果这是实际表格,而不仅仅是说明性的示例,那为什么不使用带有计算得出的Total列的视图呢? Then you have no need for processing rows with console apps, and no need to lock any rows. 然后,您无需使用控制台应用程序处理行,也无需锁定任何行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM