ASP.Net-Mvc5:LINQ,保存重复记录问题

时间:2018-10-31 11:45:24

标签: c# asp.net asp.net-mvc linq model-view-controller

我正在编码每日计数器。数据库计数器表为空。如果某人是我今天的第一位访问者,那么我正在向数据库添加一条记录,并且我将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;
    }

2 个答案:

答案 0 :(得分:0)

这是一个很常见的并发问题,即竞争条件。您将不得不Lock围绕读取和随后更新/插入值的代码进行操作。或者,您应该调用存储过程,并将所有逻辑包含在存储过程中。

如果您打算使用Web场或运行此MVC应用程序的多个实例,

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();
}