这可能是一个很长的帖子,但请耐心等待。基本思路是:
public int InsertPersonAndGetPersonId(Person person){
_dbContext.Insert(person);
return person.PersonId;
}
上述方法很简单,但违反了清晰的编程原则。
当我评估不同的方法时,我通常会列出利弊,并选择利弊最少且权衡最少的方法。因此,老实说,上述方法看起来比下面列出的替代方案更好。但我仍然希望得到SO社区的意见,也许我会学习一种最适合这一挑战的新模式。
另一种方法是使用两种方法。当一个是插入新记录时,另一个从数据库中获取最后添加的personId
。但这是不可靠的,除非您阻止数据库在插入记录和从数据库中获取其ID之间接受新人插入。
您甚至可以在从数据库获取记录时通过Person
(例如Name
)的属性进行过滤,但除了我上面所说的,还可以有多个人谁具有相同的名称但PersonId
s。
它还在进行一次数据库访问。我是一个务实的人,不想在没有实际测量的情况下推测性能。但是,如果我可以通过简单的改变来防止某些事情,甚至会略微提高性能,那么我觉得不这样做是愚蠢的。当然,在执行此操作时,我也会考虑清洁代码实践。
另一种方法可以是更改InsertPersonAndGetPersonId
,并具有以下内容:
public class PersonRepository
{
private int _personId;
public void InsertPerson(Person person){
_dbContext.Insert(person);
_personId = person.PersonId;
}
public int GetLastPersonId
return _personId;
}
}
即使我不喜欢此方法的名称GetLastPersonId()
,但这可能会带来与预期不同的personId
,但让我们假设它返回id
} person
对象。它是坏的原因,除了我已经说过,它正在修改对象的状态,因此有副作用。
我们可以简单地使用以下方法:
public void InsertPerson(Person person){
_dbContext.Insert(person);
_personId = person.PersonId;
}
由于person
是引用类型,我们可以访问person.PersonId
,如下所示:
var personRepository = new PersonRepository();
var person = new Person() {Name="Hello"};
personRepository.InsertPerson(person);
Console.WriteLine(person.PersonId);
我喜欢它吗?没有!这是太隐蔽和不可预测的,你不会真正了解它,除非你检查实现细节,然后我们打破抽象的美丽。
我们可以使用out
,如下所示:
public void InsertPerson(Person person, out int personId){
_dbContext.Insert(person);
personId = person.PersonId;
}
但这看起来比第一个InsertPersonAndGetPersonId
更愚蠢和笨拙。如果我将不得不返回一些内容,那么我将使用return
返回它,并使开发人员更明确地签名。事实上,当我们需要返回多个值时,out
和ref
更有意义。例如TryParse()
,返回boolean
,但您也可以使用out
或ref
获取解析后的值。
由于一些评论,我决定更多地澄清我的问题。我要问的是如何在不违反清洁代码原则的情况下获得PersonId
。我正在使用EF,因此从数据库获取id不是问题,事实上你可以在我的第一个例子中看到它。对不起,感到困惑。
答案 0 :(得分:2)
你考虑过举办活动吗? PersonCreatedEvent
另请参阅:http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/
答案 1 :(得分:0)
显然你的设计有问题。您返回此PersonId的事实意味着您需要它来识别域逻辑中的人(如果您愿意,则为业务逻辑)。
问题是:什么数据库ID与人物身份有关?它在您的域名中是否有任何意义? 如果没有,则使用其他方法来识别域逻辑中的Person。这将至少为您带来以下好处:
您将能够创建具有Factory的人员(如果它是一个实体并且可能是聚合根),使他对您的域逻辑身份有意义。
您将能够使用存储库保存新创建的人员,并且不必在您的域逻辑中处理它的数据库ID。
然后你就能写出这样的东西:
var newPerson = PersonFactory.Create();
//do some work with person in domain logic
PersonRepository.Persist(newPerson);