错误: 如果事件源自另一台计算机,则必须随事件一起保存显示信息。
活动中包含以下信息:
对象引用未设置为对象的实例。在 System.Data.Objects.ObjectStateManager.DetectConflicts(IList
1 entries) at System.Data.Objects.ObjectStateManager.DetectChanges() at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force) at System.Data.Entity.Internal.Linq.InternalSet
1.ActOnSet(Action action, EntityState newState,Object entity,String methodName)at System.Data.Entity.Internal.Linq.InternalSet1.Add(Object entity)
1.添加(TEntity实体)at ESHealthCheckService.BusinessFacade.BusinessOperationsLayer.AddErrorToDbObject(例外 例如,Server serverObj,Service windowsServiceObj)
at System.Data.Entity.DbSet
消息资源存在,但在字符串/消息表
中找不到该消息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);
}
}
然后调用以下函数将对象从静态列表添加到db对象。
public void AddErrorToDbObject() { 尝试 { foreach(eshealthCheckLoggingList中的EShelathLoging eslogObject) { 锁(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`
}
答案 0 :(得分:1)
DbSet<T>
不是线程安全的,因此您不能同时在多个线程中使用它。看来你正试图通过使用lock
来解决这个问题,但你做错了。为此,所有线程都必须共享一个锁对象。像你现在一样,为每个线程设置单独的锁定对象将不会做任何事情。
答案 1 :(得分:0)
请注意,我收到了与我正在处理的应用程序相同的异常,并确定解决问题的最佳方法是添加AsyncLock,因为@svick提到DbSet不是线程安全的。谢谢,@ svick!
我猜你的DbContext在你的businessLayerObj中,所以这是我推荐的,使用Stephen Cleary的优秀Nito.AsyncEx(见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...
});
}