我有一种方法可以在数据库中创建一些条目并返回 Id 。我想以某种方式将这两者分开,因为它违反了命令查询分离 例如方法(简化):
int CreatePost(database::Post newPost)
{
using(var db = new database::MainModelContainer())
{
db.Posts.Add(newPost);
db.SaveChanges();
return newPost.Id;
}
}
我知道有使用 ref 或 out 的解决方法,但我认为这些解决方案 unclean 。 我希望得到以下签名的命令。
void CreatePost(database::Post newPost)
我有办法实现这个目标吗? 注意: 我需要在创建后立即知道新创建的条目 的 ID 。
答案 0 :(得分:2)
保存实体后,Entity Framework会使用适当的值填充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 :(得分:1)
这可以用memento模式解决,除了你似乎不需要memento附带的所有撤消能力。在插入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
每次创建新帖子时,您都会构建其中一个创建者来为您完成。您可以随时查询{{1}}属性,而无需考虑影响状态。
答案 2 :(得分:1)
Mark Seemann在http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/处对这个问题给出了很好的答案。
短版本不依赖于数据库生成的ID,而是创建自己的密钥并使用它(他建议使用GUID)。
数据库仍然可以为内部使用生成身份密钥;这些可以通过遵守CQS来查询。这实际上实现了几个好的做法:它将应用程序与数据库实现分开(并非所有数据库都有自动生成身份或实现相同),并且它本身不鼓励将内部顺序ID暴露给用户,这可能是一个安全漏洞(OWASP)前10名#4不安全直接对象参考)。