1

Error : If the event originated on another computer, the display information had to be saved with the event.

The following information was included with the event:

Object reference not set to an instance of an object. at System.Data.Objects.ObjectStateManager.DetectConflicts(IList1 entries) at System.Data.Objects.ObjectStateManager.DetectChanges() at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force) at System.Data.Entity.Internal.Linq.InternalSet1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) at System.Data.Entity.Internal.Linq.InternalSet1.Add(Object entity)
at System.Data.Entity.DbSet
1.Add(TEntity entity) at ESHealthCheckService.BusinessFacade.BusinessOperationsLayer.AddErrorToDbObject(Exception ex, Server serverObj, Service windowsServiceObj)

the message resource is present but the message is not found in the string/message table

public void CheckForServerHealth()
        {
            businessLayerObj.SetStartTimeWindowsService();
            List<ServerMonitor> serverMonitorList = new List<ServerMonitor>();
            serverList = businessLayerObj.GetServerList();
            Parallel.ForEach(
          serverList,
          () => new List<ServerMonitor>(),
          (server, loop, localState) =>
          {
              localState.Add(serverStatus(server, new ServerMonitor()));
              return localState;
          },
              localState =>
              {
                  lock (serverMonitorList)
                  {
                      foreach (ServerMonitor serverMonitor in localState)
                      {
                          serverMonitorList.Add(serverMonitor);
                      }
                  }
              });
            businessLayerObj.SaveServerHealth(serverMonitorList);
        }


public ServerMonitor serverStatus(Server serverObj, ServerMonitor serverMonitorObj)
        {
            if (new Ping().Send(serverObj.ServerName, 30).Status == IPStatus.Success)
            {
                serverMonitorObj.Status = true;
                try
                {
                    PerformanceCounter cpu = new PerformanceCounter("Processor", "% Processor Time", "_Total", serverObj.ServerName);
                    serverMonitorObj.CPUUtlilization = (cpu.NextValue());
                }
                catch (Exception ex)
                {
                    businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
                }

                serverMonitorObj.ServerID = serverObj.ServerID;
                try
                {
                    string[] diskArray = serverObj.DriveMonitor.ToString().Split(':');
                    if (diskArray != null && diskArray.Contains("NA"))
                    {
                        serverMonitorObj.DiskSpace = "NA";
                    }
                    else
                    {
                        serverMonitorObj.DiskSpace = ReadFreeSpaceOnNetworkDrives(serverObj.ServerName, diskArray);
                    }
                }
                catch (Exception ex)
                {
                    businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
                }

                serverMonitorObj.CreatedDateTime = DateTime.Now;
            }
            else
            {
                serverMonitorObj.Status = false;
                serverMonitorObj.ServerID = serverObj.ServerID;
                //return serverMonitorObj;
            }

            return serverMonitorObj;
        }



public void AddErrorObjectToStaticList(Exception ex, Server serverObj = null, Service windowsServiceObj = null)
        {
            EShelathLoging esLogger = new EShelathLoging();

            esLogger.CreateDatetime = DateTime.Now;
            if (ex.InnerException != null)
            {
                esLogger.Message = (windowsServiceObj == null ? ex.InnerException.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message));
                //esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message;
                esLogger.StackTrace = (ex.InnerException.StackTrace == null ? "" : ex.InnerException.StackTrace);
            }
            else
            {
                esLogger.Message = (windowsServiceObj == null ? ex.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message));
                //esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message;
                esLogger.StackTrace = ex.StackTrace;
            }

            if (serverObj != null)
            {
                esLogger.ServerName = serverObj.ServerName;
            }
            try
            {
                lock (lockObject)
                {
                    esHealthCheckLoggingList.Add(esLogger);
                }
            }
            catch (Exception exe)
            {
                string logEntry = "Application";

                if (EventLog.SourceExists(logEntry) == false)
                {
                    EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
                }

                EventLog eventLog = new EventLog();
                eventLog.Source = logEntry;
                eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
            }
        }

And then the below function is called to add objects from static list to the db object.

public void AddErrorToDbObject() { try { foreach (EShelathLoging eslogObject in esHealthCheckLoggingList) { lock (lockObject) { dbObject.EShelathLogings.Add(eslogObject); } } } catch (DbEntityValidationException exp) { string logEntry = "Application";

            if (EventLog.SourceExists(logEntry) == false)
            {
                EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
            }

            EventLog eventLog = new EventLog();
            eventLog.Source = logEntry;
            eventLog.WriteEntry(exp.Message + " " + exp.StackTrace, EventLogEntryType.Error);
        }
        catch (Exception exe)
        {
            string logEntry = "Application";

            if (EventLog.SourceExists(logEntry) == false)
            {
                EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
            }

            EventLog eventLog = new EventLog();
            eventLog.Source = logEntry;
            eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
        }`enter code here`

    }
3
  • How are you calling this method? I dont see the Parallel.ForEach? Commented Oct 1, 2014 at 17:14
  • This function is called from a method which is invoked in Parallel.Foreach loop ie in a multithreaded environment..... Commented Oct 1, 2014 at 17:51
  • There is no point in using Parallel.ForEach when you're using a locking on a shared context. Moreso, you're using the lock statement wrong. Commented Oct 1, 2014 at 18:50

2 Answers 2

1

DbSet<T> is not thread-safe, so you can't use it from multiple threads at the same time. It seems you're trying to fix that by using a lock, but you're doing that incorrectly. For this to work, all threads have to share a single lock object. Having separate lock object for each thread, like you do now, won't do anything.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the point... can you plesae let me know how to do it I'm really confused with the lock in multi threaded environment...
@Harry Well, that's hard to say without seeing your Parallel.ForEach() code or more of your code in general. But usually, the lock object should be where your thread-un-safe object is (I assume here it's an instance field), or, even better, it should be the thread-un-safe object itself (i.e. lock (dbObject)).
Ahhh!! yes I missed the basic purpose of lock.. it might slow down my threads but thanks once again for pointing in the right direction.. I'll try that...
I've posted my code it's too clumsy to read First code snippet is the place where I'm calling the second function(serverStatus) in which I'm calling the function to collect the db errors
@Harry You can edit your question and add that code there. Long pieces of code in comments indeed don't work well.
|
0

Please note that I received the same exception with the application I was working on, and determined that the best way to resolve the issue was to add an AsyncLock, because of what @svick mentioned about how DbSet is not threadsafe. Thank you, @svick!

I'm guessing that your DbContext is inside your businessLayerObj, so here is what I recommend, using Stephen Cleary's excellent Nito.AsyncEx (see https://www.nuget.org/packages/Nito.AsyncEx/):

using Nito.AsyncEx;
// ...

private readonly AsyncLock _dbContextMutex = new AsyncLock();


public void CheckForServerHealth()
{
        using (await _dbContextMutex.LockAsync().ConfigureAwait(false))
        {
            await MyDbContextOperations(businessLayerObj).ConfigureAwait(false);
        }
}

private async Task MyDbContextOperations(BusinessLayerClass businessLayerObj)
{
        await Task.Run(() =>
        {
            // operations with businessLayerObj/dbcontext here...
        });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.