1
我正在使用PostSharp處理實體框架6異常。正如你可以在代碼中看到下面我處理兩種不同類型的異常:PostSharp OnExceptionAspect + EF 6 DbUpdateException
- DbEntityValidationException
- DbUpdateException
現在,我HandleExceptionAttribute
能夠捕獲所有DbEntityValidationException
但由於某些原因,HandleExceptionAttribute
永遠不會執行,每當EF投擲一個DbUpdateException
這是我的代碼,讓你有tter理解:
HandleExceptionAttribute.cs
[Serializable]
public class HandleExceptionAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
Exception exception = args.Exception;
var validationException = exception as DbEntityValidationException;
if (validationException != null)
{
HandleDataValidationException(validationException);
}
var updateException = exception as DbUpdateException;
if (updateException != null)
{
HandleDataUpdateException(updateException);
}
throw exception;
}
private void HandleDataUpdateException(DbUpdateException exception)
{
Exception innerException = exception.InnerException;
while (innerException.InnerException != null)
{
innerException = innerException.InnerException;
}
throw new Exception(innerException.Message);
}
private void HandleDataValidationException(DbEntityValidationException exception)
{
var stringBuilder = new StringBuilder();
foreach (DbEntityValidationResult result in exception.EntityValidationErrors)
{
foreach (DbValidationError error in result.ValidationErrors)
{
stringBuilder.AppendFormat("{0} [{1}]: {2}",
result.Entry.Entity.ToString().Split('.').Last(), error.PropertyName, error.ErrorMessage);
stringBuilder.AppendLine();
}
}
throw new Exception(stringBuilder.ToString().Trim());
}
}
MyContext.cs
public class MyContext : DbContext
{
public MyContext() : base(Settings.Get(Settings.DB_CONNECTION_STRING)) { }
public DbSet<Subscriber> Subscribers { get; set; }
private void SetCreatedAtUpdatedAt()
{
foreach (DbEntityEntry entityEntry in ChangeTracker.Entries())
{
switch (entityEntry.State)
{
case EntityState.Added:
((IEntity) entityEntry.Entity).CreatedAt = DateTime.Now;
break;
case EntityState.Modified:
((IEntity) entityEntry.Entity).UpdatedAt = DateTime.Now;
break;
}
}
}
[HandleException]
public override int SaveChanges()
{
SetCreatedAtUpdatedAt();
return base.SaveChanges();
}
[HandleException]
public override Task<int> SaveChangesAsync()
{
SetCreatedAtUpdatedAt();
return base.SaveChangesAsync();
}
}
行動
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Subscribe(string email)
{
string message = null;
bool success = false;
try
{
using (var context = new MyContext())
{
context.Subscribers.Add(
new Subscriber
{
Email = email
});
await context.SaveChangesAsync();
}
await _queueManager.Enque(
QueueNames.TASK_SEND_EMAIL,
new BrokeredMessage(email),
Settings.Get(Settings.SB_CN_TASKS_SEND));
success = true;
}
catch (Exception exception)
{
// Whenever there is a DbUpdateException, it does not get
// filtered and processed by PostSharp Exception Handler
// I have a unique index constraint on the "Email" field of the Subscriber.
// So when I try to add a duplicate subscriber, EF raises DbUpdateException
// This exception should have been filtered by PostSharp since I have
// overridden and decorated "SaveChangesAsync()" method in my DbContext
// with [HandleException]
// On the other hand, I also have [Required] for "Email" in my POCO.
// So, when I don't pass in any email address for the subscriber,
// EF raises DbEntityValidationException -- this does get processed
// by the PostSharp Exception Handler
message = exception.Message;
}
return Json(new {message, success});
}
所以我猜數據驗證不是異步執行的。任何(乾淨)我可以在這期間做什麼? – Moon
有一個解決方法:您可以使用方法攔截屬性來應用您的異常處理邏輯,但這需要您深入研究'async'方法的編譯器生成類型的細節。這非常麻煩,需要PostSharp的付費版本,並且確實限制瞭如何組播這些屬性。 –