我想要實現的是我的網站發出一條消息,並將它放在總線上,一個服務將它拾起並寫入數據庫,並通過審計自動填充AddedBy/UpdatedBy字段該行。在不同的線程上運行的NServiceBus和NHibernate EventListeners
我通過使用NServiceBus IMessageMutator組件將用戶ID寫入來自我的ASP.Net應用程序中登錄用戶的Thread.CurrentPrincipal的消息頭中。 在我的服務中,我使用一個IMessageModule來提取這個頭並將其綁定到Thread.CurrentPrincipal。這很好,在我的消息處理程序中,我可以看到Thread.CurrentPrincipal.Identity.Name正確綁定到在Web應用程序中引發消息的用戶標識。
利用NHibernate的IPreUpdateEventListener/IPreInsertEventListener我將每個實體的AddedBy/UpdatedBy設置寫入數據庫之前。這在網站上完美運行,但在我的NServiceBus服務中,偵聽器運行的線程與處理程序運行的線程不同,這意味着線程的CurrentPrincipal不再是IMessageModule中綁定的ID。
我可以看到NHibernate在調用堆棧中使用DistributedTransactionFactory,我懷疑這是造成我的問題的原因。我不想失去事務性,如果提交失敗,則不會重新嘗試或放置在錯誤隊列中,並且如果從隊列中移除消息失敗,並且更新不會回滾到數據庫。
我瀏覽過網頁,所有例子都利用線程的CurrentPrincipal來綁定修改行的用戶的ID。我正在尋找的是一種將NHibernate偵聽器保留在與消息處理程序相同的線程上的方法,或將用戶ID傳遞給偵聽器,以便在將實體寫入數據庫之前綁定到實體。
這裏是我的聽衆,我省略了它
public class EntityPersistenceListener : IPreUpdateEventListener, IPreInsertEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
var audit = @event.Entity as EntityBase;
if (audit == null)
return false;
var time = DateTimeFactory.GetDateTime();
var name = Thread.CurrentPrincipal.Identity.Name;
Set(@event.Persister, @event.State, "AddedDate", audit.AddedDate);
Set(@event.Persister, @event.State, "AddedBy", audit.AddedBy);
Set(@event.Persister, @event.State, "UpdatedDate", time);
Set(@event.Persister, @event.State, "UpdatedBy", name);
audit.AddedDate = audit.AddedDate;
audit.AddedBy = audit.AddedBy;
audit.UpdatedDate= time;
audit.UpdatedBy = name;
return false;
}
}
發現設置方法這裏是NServiceBus消息模塊中提取ID,並將其綁定到當前線程的身份
public class TenantAndInstanceInfoExtractor : IMessageModule
{
private readonly IBus _bus;
public TenantAndInstanceInfoExtractor(IBus bus)
{
_bus = bus;
}
public void HandleBeginMessage()
{
var headers = _bus.CurrentMessageContext.Headers;
if (headers.ContainsKey("TriggeredById"))
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(headers["TriggeredById"]), null);
else
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(string.Empty), null);
}
public void HandleEndMessage()
{
}
public void HandleError() { }
}
Morgan。我無法完全理解您的要求。你下週有時間撥打Skype電話嗎?我是「simon.cropp」上的Skype – Simon
嗨西蒙,是的請。我會通過電子郵件安排時間。 – Morgan