我正在编码每日计数器。数据库计数器表为空。如果某人是我今天的第一位访问者,那么我正在向数据库添加一条记录,并且我将counter = 1设置为;此后,当其他访客访问当天时,我将增加计数器++,并更新记录。
所以我的记录必须是这样的:
日期:2018-10- 01 计数器:23
日期:2018-10- 02 计数器:65
日期:2018-10- 03 计数器:20
日期:2018-10- 04 计数器:89
我的问题是:如果网站同时吸引到访问者,则linq会在当天保存2条记录。像这样:
日期:2018-10- 01 计数器:23
日期:2018-10-02计数器:1 //第一条记录:计数器= 1
日期:2018-10-02 counter:65 //第二条记录:counter = 65
日期:2018-10- 03 计数器:20
日期:2018-10- 04 计数器:1 //第一条记录
日期:2018-10- 04 计数器:89 //第二条记录
日期必须唯一。我该如何解决这个问题?我的代码如下。非常感谢。
public static int IncreaseCounter_DailySiteVisitors()
{
int counter = 0;
using (var context = new MyProjectEntities())
{
try
{
string format = "dd.MM.yyyy";
DateTime Today = DateTime.Now;
var obj = (from record in context.CounterDailySiteVisitor
where
record.DateRecord != null
&& record.DateRecord.HasValue
&& record.DateRecord.Value.Year == Today.Year
&& record.DateRecord.Value.Month == Today.Month
&& record.DateRecord.Value.Day == Today.Day
select record).FirstOrDefault();
//var obj = context.CounterDailyVisitor.Where(x => x.DateRecord != null && ((DateTime)x.DateRecord).ToString("yyyy.MM.dd") == DateTime.Now.ToString("yyyy.MM.dd")).FirstOrDefault();
if (obj != null)
{
counter = obj.Count ?? 0;
counter++;
obj.Count = counter;
context.SaveChanges();
}
else
{
var newRecordObj = context.CounterDailySiteVisitor.Create();
newRecordObj.Count = 1;
newRecordObj.DateRecord = Today;
context.CounterDailySiteVisitor.Add(newRecordObj);
context.SaveChanges();
}
}
catch (Exception e)
{
}
}
return counter;
}
答案 0 :(得分:0)
这是一个很常见的并发问题,即竞争条件。您将不得不Lock
围绕读取和随后更新/插入值的代码进行操作。或者,您应该调用存储过程,并将所有逻辑包含在存储过程中。
Lock
会带来一系列问题。
答案 1 :(得分:0)
被两个线程同时击中的机会非常低。 但我想从技术上讲可以,所以您需要将其包装在一个锁中
类似下面的内容...
public static int IncreaseCounter_DailySiteVisitors()
{
private readonly object somethingObject = new object();
var context = new MyProjectEntities()
var today = DateTime.Now;
var todaysRecord = context.CounterDailyVisitor
.SingleOrDefault(x => x.DateRecord.Year == Today.Year
&& x.DateRecord.Month == Today.Month
&& x.DateRecord.Day == Today.Day
);
if (todaysRecord != null)
{
//the existing count + 1
todaysRecord.Count = todaysRecord.Count++;
}
else
{
Lock(somethingObject)
{
//recheck
var todaysRecord = context.CounterDailyVisitor
.SingleOrDefault(x => x.DateRecord.Year == Today.Year
&& x.DateRecord.Month == Today.Month
&& x.DateRecord.Day == Today.Day
);
if (todaysRecord != null)
{
//the existing count + 1
todaysRecord.Count = todaysRecord.Count++;
}
else
{
var newRecordObj = new CounterDailyVisitor();
newRecordObj.Count = 1;
newRecordObj.DateRecord = DateTime.Now; //this shouldnt be nullable
context.CounterDailySiteVisitor.Add(newRecordObj);
}
}
}
context.SaveChanges();
}