1

我有一個方法可以在數據庫中創建一些條目並返回它的Id。我想以某種方式分開這兩個,因爲它違反了Command-Query Separation。
例如在創建新的數據庫條目時違反命令查詢分隔

int CreatePost(database::Post newPost) 
{ 
    using(var db = new database::MainModelContainer()) 
    { 
     db.Posts.Add(newPost); 
     db.SaveChanges(); 
     return newPost.Id; 
    } 
} 

我知道有使用裁判解決方法,但我認爲這些解決方案不潔:方法(簡化)。 我想要簽署以下命令。

void CreatePost(database::Post newPost) 

有沒有辦法讓我做到這一點?
注意: 我需要知道什麼是Id新創建的條目立即它創建後。

+0

用於命令查詢分隔提及的+1。 –

回答

1

這可以用一個備忘錄模式來解決,除了你似乎並不需要記憶帶來的所有撤消能力。一些簡單的捕捉Post對象的狀態已經插入後會工作:

public class PostCreator 
{ 
    public PostCreator() 
    { 
     CreatedId = null; 
    } 

    public void CreatePost(database::Post newPost) 
    { 
     if (CreatedPostId != null) 
      throw new InvalidOperationException("Post Already Created!"); 

     using(var db = new database::MainModelContainer()) 
     { 
      db.Posts.Add(newPost); 
      db.SaveChanges(); 
      CreatedPostId = newPost.Id; 
     } 
    } 

    public int? CreatedPostId { get; private set; } 
} 

每次創建一個新的職位時,你會建造這些創作者爲你做一個。您可以隨時查詢CreatedPostId屬性,而不用擔心影響狀態。

+0

這似乎與ref或out類似,但更「複雜」(更抽象)。也許沒有更好的解決方案? 感謝您的幫助! :) – kr85

2

保存實體後,實體框架使用適當的值填充Id屬性。所以,如果你有一個實體:

public class Post 
{ 
    public int Id { get; set; } // primary key 
    ... 
} 

這將其保存方法:

public void SavePost(Post post) 
{ 
    using (var db = new YourDatabase()) 
    { 
     db.Posts.Add(post); 
     db.SaveChanges(); 
    } 
} 

您可以從客戶端代碼做到這一點,以獲得ID:

var myPost = new Post(); 
Console.Writeline(myPost.Id); // displays 0 
SavePost(myPost); 
Console.Writeline(myPost.Id); // displays the new id 
1

有一個Mark Seemann在http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/對這個問題的出色答案。

簡短版本不依賴於數據庫生成的ID,而是創建自己的密鑰並使用它(他建議使用GUID)。

數據庫可能仍然會爲其內部使用生成身份密鑰;儘管如此,這些可以通過CQS來查詢。這實際上實現了一些好的做法:它將應用程序從數據庫實現中分離出來(並非所有數據庫都具有自動生成身份或者實現相同的功能),並且它固有地阻止將內部連續ID公開給可能成爲安全漏洞的用戶(OWASP前10#4不安全直接對象參考)。

相關問題