2013-01-23 4 views
2

업데이트 : 우리는 점점 더 System.Data.SqlClient.SqlException을 얻고 있습니다. 메시지는 다음과 같습니다.EventStore 중복 커밋 예외

'PK_Commits'PRIMARY KEY 제약 조건 위반. 'dbo.Commits'개체에 중복 키를 삽입 할 수 없습니다. \\ 문이 종료되었습니다.

EventStore에서 streamid 및 commitid를 고유 ID로 사용하고있는 것 같습니다.

다음과 같이 이벤트 저장소를 사용하여 이벤트를 추가합니다.

public bool TryAppend(object[] content) 
{ 
    if (content == null) 
     throw new ArgumentNullException("content"); 

    try 
    { 
     using (var stream = m_storage.OpenStream(m_streamID, 0, int.MaxValue)) 
     { 
      var versionInStore = stream.StreamRevision; 

      content.ToList().ForEach(m => 
      { 
       var version = ++versionInStore; 
       var key = string.Format("{0}-{1:00000000}", m.GetType().Name, version); 

       var savedMessage = new SavedRecord(key, version, m); 

       stream.Add(new EventMessage { Body = savedMessage }); 
      }); 

      stream.CommitChanges(Guid.NewGuid()); 
     } 

     return true; 
    } 
    catch (Exception e) 
    { 
     m_logger.LogError(e); 

     return false; 
    } 
} 

EventStore의 구성은 다음과 같습니다. 우리는 Sql Serer 2008을 지속성 저장소로 사용하고 있습니다.

return Wireup.Init() 
    .LogToOutputWindow() 
     .UsingSqlPersistence(m_connectionName) 
     .WithDialect(new MsSqlDialect()) 
     .EnlistInAmbientTransaction() // two-phase commit 
    .InitializeStorageEngine() 
    .UsingJsonSerialization() 
     .Compress() 
    .UsingSynchronousDispatchScheduler() 
     .DispatchTo(new DelegateMessageDispatcher(DispatchCommit)) 
    .Build(); 

어떤 아이디어가 왜 dupplicate 커밋 예외가 발생합니까?

감사합니다.

답변

0

같은 문제가 있습니다. 내 경우에는 다른 스레드가 같은 id의 스트림에 동시에 다른 이벤트를 추가했기 때문일 수 있습니다. 은 추가 이벤트를 다시 시도 할 수 있도록 다음 코드를 writtent 적이 :

private void TryAddEvent(IStoreEvents storeEvents, IUserEvent anEvent, Guid streamId) 
{ 
    var isCommitSuccessful = false; 
    for (var i = 0; i < 10 && !isCommitSuccessful; i++) 
    { 
     try 
     { 
      using (var stream = storeEvents.OpenStream(streamId, 0, int.MaxValue)) 
      { 
       stream.Add(new EventMessage {Body = anEvent}); 
       if (stream.UncommittedEvents.All(e => e.Body != anEvent)) 
       { 
        stream.Add(new EventMessage {Body = anEvent}); 
       } 
       stream.CommitChanges(Guid.NewGuid()); 
      } 
      isCommitSuccessful = true; 
     } 
     catch (Exception ex) 
     { 
      if (!(ex is SqlException) && !(ex is ConcurrencyException)) 
      { 
       throw; 
      } 
      using (var stream = storeEvents.OpenStream(streamId, 0, int.MaxValue)) 
      { 
       if (stream.CommittedEvents.Any(e => e.Body == anEvent)) 
       { 
        isCommitSuccessful = true; 
       } 
      } 
     } 
    } 

    if (!isCommitSuccessful) 
    { 
     throw new ConcurrencyException(String.Format("Cannot add {0} to event store", anEvent.GetType())); 
    } 
} 

은 도움이 될 바랍니다.

+0

감사합니다. Yuriy, 나는 이것을 시도 할 것입니다. 이 문제를 해결하기 위해 더 간단한 솔루션으로 변했습니다. EventStore 라이브러리를 제거하고 바이너리 직렬화를 통해 SQL Server 테이블에 메시지를 저장했습니다. Lokad CQRS 이벤트 저장과 매우 ​​유사합니다. –