Linq to sql Linq到SQL并发问题
你好 我有一个可以调用多个方法的web服务。每次调用其中一个方法时,我都会记录对统计数据库的调用,这样我们就知道每个方法每月调用多少次以及平均处理时间 每次记录统计数据时,我都会首先检查数据库,看看当前月份的方法是否已经存在,如果不存在,则创建并添加行。如果它已经存在,我会将所需的列更新到数据库中 我的问题是,有时当我更新一行时,我会得到“未找到或更改的行”异常,是的,我知道这是因为我读取该行后该行已被修改 为了解决这个问题,我尝试使用以下方法,但没有成功:Linq to sql Linq到SQL并发问题,linq-to-sql,concurrency,Linq To Sql,Concurrency,你好 我有一个可以调用多个方法的web服务。每次调用其中一个方法时,我都会记录对统计数据库的调用,这样我们就知道每个方法每月调用多少次以及平均处理时间 每次记录统计数据时,我都会首先检查数据库,看看当前月份的方法是否已经存在,如果不存在,则创建并添加行。如果它已经存在,我会将所需的列更新到数据库中 我的问题是,有时当我更新一行时,我会得到“未找到或更改的行”异常,是的,我知道这是因为我读取该行后该行已被修改 为了解决这个问题,我尝试使用以下方法,但没有成功: 在我的datacontext周围使
- 在我的datacontext周围使用
- 在TransactionScope周围使用
- 使用互斥锁,这不起作用,因为web服务(我不确定我称之为正确的想法)在不同的PC上复制,以提高性能,但仍然使用相同的数据库
- 解决异常中的并发冲突,这不起作用,因为我需要获取新的数据库值并向其添加值
public class StatisticsGateway : IStatisticsGateway
{
#region member variables
private StatisticsDataContext db;
#endregion
#region Singleton
[ThreadStatic]
private static IStatisticsGateway instance;
[ThreadStatic]
private static DateTime lastEntryTime = DateTime.MinValue;
public static IStatisticsGateway Instance
{
get
{
if (!lastEntryTime.Equals(OperationState.EntryTime) || instance == null)
{
instance = new StatisticsGateway();
lastEntryTime = OperationState.EntryTime;
}
return instance;
}
}
#endregion
#region constructor / initialize
private StatisticsGateway()
{
var configurationAppSettings = new System.Configuration.AppSettingsReader();
var connectionString = ((string)(configurationAppSettings.GetValue("sqlConnection1.ConnectionString", typeof(string))));
db = new StatisticsDataContext(connectionString);
}
#endregion
#region IStatisticsGateway members
public void AddStatisticRecord(StatisticRecord record)
{
using (db)
{
var existing = db.Statistics.SingleOrDefault(p => p.MethodName == record.MethodName &&
p.CountryID == record.CountryID &&
p.TokenType == record.TokenType &&
p.Year == record.Year &&
p.Month == record.Month);
if (existing == null)
{
//Add new row
this.AddNewRecord(record);
return;
}
//Update
existing.Count += record.Count;
existing.TotalTimeValue += record.TotalTimeValue;
db.SubmitChanges();
}
}
我建议让SQL Server处理并发性。 以下是方法:
sp_getapplock
。只是说说而已。但考虑到互联网上的所有示例,这似乎相当简单。)如果您试图避免存储过程,那么这个解决方案显然不适合您,但这是我轻松快速地解决它的方法。希望有帮助 我建议让SQL Server处理并发性。 以下是方法:
sp_getapplock
。只是说说而已。但考虑到互联网上的所有示例,这似乎相当简单。)如果您试图避免存储过程,那么这个解决方案显然不适合您,但这是我轻松快速地解决它的方法。希望有帮助 如果您不想使用存储过程方法,那么处理它的一种粗略方法就是在特定异常上重试。例如:
int maxRetryCount = 5;
for (int i = 0; i < maxRetryCount; i++)
{
try
{
QueryAndUpdateDB();
break;
}
catch(RowUpdateException ex)
{
if (i == maxRetryCount) throw;
}
}
int maxRetryCount=5;
对于(int i=0;i
如果您不想使用存储过程方法,处理它的一种粗略方法就是在特定异常上重试。例如:
int maxRetryCount = 5;
for (int i = 0; i < maxRetryCount; i++)
{
try
{
QueryAndUpdateDB();
break;
}
catch(RowUpdateException ex)
{
if (i == maxRetryCount) throw;
}
}
int maxRetryCount=5;
对于(int i=0;i
我没有使用sp_getapplock,而是使用了HOLDLOCK和ROWLOCK,如下所示:
CREATE PROCEDURE [dbo].[UpdateStatistics]
@MethodName as varchar(50) = null,
@CountryID as varchar(2) = null,
@TokenType as varchar(5) = null,
@Year as int,
@Month as int,
@Count bigint,
@TotalTimeValue bigint
作为
开始
不计数
BEGIN TRAN
UPDATE dbo.[Statistics]
WITH (HOLDLOCK, ROWLOCK)
SET Count = Count + @Count
WHERE MethodName=@MethodName and CountryID=@CountryID and TokenType=@TokenType and Year=@Year and Month=@Month
IF @@ROWCOUNT=0
INSERT INTO dbo.[Statistics] (MethodName, CountryID, TokenType, TotalTimeValue, Year, Month, Count) values (@MethodName, @CountryID, @TokenType, @TotalTimeValue, @Year, @Month, @Count)
COMMIT TRAN
结束
去
我通过多个线程同时调用我的web服务方法进行了测试,每次调用都记录在案,没有出现任何问题。我没有使用sp_getapplock,而是使用了HOLDLOCK和ROWLOCK,如下所示:
CREATE PROCEDURE [dbo].[UpdateStatistics]
@MethodName as varchar(50) = null,
@CountryID as varchar(2) = null,
@TokenType as varchar(5) = null,
@Year as int,
@Month as int,
@Count bigint,
@TotalTimeValue bigint
作为
开始
不计数
BEGIN TRAN
UPDATE dbo.[Statistics]
WITH (HOLDLOCK, ROWLOCK)
SET Count = Count + @Count
WHERE MethodName=@MethodName and CountryID=@CountryID and TokenType=@TokenType and Year=@Year and Month=@Month
IF @@ROWCOUNT=0
INSERT INTO dbo.[Statistics] (MethodName, CountryID, TokenType, TotalTimeValue, Year, Month, Count) values (@MethodName, @CountryID, @TokenType, @TotalTimeValue, @Year, @Month, @Count)
COMMIT TRAN
结束
去
我通过多线程同时调用我的web服务方法进行了测试,每次调用都记录在案,没有任何问题。感谢您的回复。我通过创建存储过程解决了这个问题!工作起来像个魔术师!只是好奇,您是否在存储过程中使用了sp_getapplock?(因为将逻辑移动到存储过程将大大减少并发问题的发生。)我使用了HOLDLOCK和ROWLOCK,请检查我的答案。感谢您的回复。我通过创建存储过程解决了这个问题!工作起来像个魔术师!只是好奇,您是否在存储过程中使用了sp_getapplock?(因为将逻辑移动到存储过程将大大减少并发问题的发生。)我使用了HOLDLOCK和ROWLOCK,请检查我的答案。