另一个异常可能来自相同的错误 - 对...的更改 数据库已成功提交,但发生错误 更新对象上下文。 ObjectContext可能位于 不一致的状态。内部异常消息:保存或接受 更改失败,因为多个类型的实体 'ClientDataStore.Logger.DB.Core.AuditLog'具有相同的主键 值。确保显式设置的主键值是唯一的。 确保正确配置数据库生成的主键 在数据库和实体框架模型中。使用实体 Database First / Model First配置的Designer。使用 'HasDatabaseGeneratedOption“”流畅的API或 用于Code First配置的'DatabaseGeneratedAttribute'; 属性“Id”是对象的关键信息的一部分,但不能 被修改
我有一个Asp.Net WebAPI应用程序,它正在使用实体框架Code First模型,我正在记录每个请求。为此目的,有一个继承DelegatingHandler的类。 我已经覆盖了SendAsync方法。
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Get data from token
IPrincipal _currentUser = HttpContext.Current.User;
// Start watch to count Milliseconds of execution of request.
var watch = Stopwatch.StartNew();
var result = await base.SendAsync(request, cancellationToken);
// Stop watch after request is complete
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
try
{
bool isRestLoggerEnabled = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["RestLoggerEnabled"]);
if (isRestLoggerEnabled && request.Headers.Authorization != null)
{
var requestBody = string.Empty;
using (var reader = new StreamReader(request.Content.ReadAsStreamAsync().Result))
{
reader.BaseStream.Seek(0, SeekOrigin.Begin);
requestBody = reader.ReadToEnd();
}
AuditLog al = new AuditLog();
al.CreateDate = DateTime.Now;
al.HTTPMethod = request.Method.Method;
al.RequestData = requestBody;
al.ResponseData = result.Content.ReadAsStringAsync().Result.ToString();
al.DurationMS = TimeSpan.FromMilliseconds(elapsedMs);
al.HTTPResponseCode = ((int)result.StatusCode).ToString();
al.RequestHeaders = request.Headers.ToString();
al.RequestURL = request.RequestUri.ToString();
if ((int)result.StatusCode != (int)HttpResponseStatusCodeTypes.Unauthorized)
{
al.UserId = ((_currentUser.Identity as ClaimsIdentity).FindFirst("UserId") != null ? long.Parse((_currentUser.Identity as ClaimsIdentity).FindFirst("UserId").Value) : 0);
al.UserPartyId = ((_currentUser.Identity as ClaimsIdentity).FindFirst("UserPartyId") != null ? long.Parse((_currentUser.Identity as ClaimsIdentity).FindFirst("UserPartyId").Value) : 0);
al.PlatformId = ((_currentUser.Identity as ClaimsIdentity).FindFirst("PlatformId") != null ? long.Parse((_currentUser.Identity as ClaimsIdentity).FindFirst("PlatformId").Value) : 0);
al.ProductId = ((_currentUser.Identity as ClaimsIdentity).FindFirst("ProductId") != null ? long.Parse((_currentUser.Identity as ClaimsIdentity).FindFirst("ProductId").Value) : 0);
}
unitOfWork.LoggerRepository<AuditLog>().Add(al);
unitOfWork.Save();
}
}
catch(Exception ex)
{
loggerManager.Critical(ex, "AuditLogger exception");
}
// Log responce and request + time and other
if (result.Content != null)
{
// once response body is ready, log it
var responseBody = await result.Content.ReadAsStringAsync();
Trace.WriteLine(responseBody);
}
return result;
}
这是表格的模型。
public class AuditLog : LoggerEntityBase
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
//[Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime? CreateDate { get; set; }
public string RequestData { get; set; }
public string ResponseData { get; set; }
[MaxLength(3)]
public string HTTPResponseCode { get; set; }
public long UserId { get; set; }
public long UserPartyId { get; set; }
public long PlatformId { get; set; }
public long ProductId { get; set; }
public long ClientId { get; set; }
[MaxLength(2000)]
public string RequestURL { get; set; }
public string HTTPMethod { get; set; }
public string RequestHeaders { get; set; }
public TimeSpan DurationMS { get; set; }
}
我还在使用unitOfWork和Repository模式。 在应用程序收到大量请求的那一刻,可能每10-15分钟就有1000个请求,并且在某些时候我得到了这些例外,而不是每次请求,但是他们每隔5-10分钟就会不断发出这样的事情或类似的事情。 。 在我看来,可能导致问题的一件事是 - 记录器正在保存的每条记录都有大量数据(如7k-10k字符)。如果应用程序一次收到许多请求,并且每个请求都包含如此多的数据,则无法使用db记录这么快,并且开始弄乱它的PK id-s。 PK是标准的sql生成的大型int。
有没有人对此处可能发生的事情有任何其他想法?