C# 通过实体框架保存收益率回报的变化
我在获取实体框架以正确保存收益率返回的结果时遇到了一个问题。为了说明这个问题,我创建了两组方法,一组返回一个实体,另一组使用yield-return返回一个IEnumerable。日志引用UserProfile 第1组:C# 通过实体框架保存收益率回报的变化,c#,entity-framework,return,yield,savechanges,C#,Entity Framework,Return,Yield,Savechanges,我在获取实体框架以正确保存收益率返回的结果时遇到了一个问题。为了说明这个问题,我创建了两组方法,一组返回一个实体,另一组使用yield-return返回一个IEnumerable。日志引用UserProfile 第1组: public static UserProfile CreateUser() { return new UserProfile() { UserId = Guid.Parse("60a3987c-0aa6-4a93- a5d2-68
public static UserProfile CreateUser()
{
return new UserProfile() {
UserId = Guid.Parse("60a3987c-0aa6-4a93- a5d2-68c51122858b"),
UserName = "jason"
};
}
public static Journal CreateJournal(UserProfile userProfile)
{
return new Journal() { UserProfile = userProfile };
}
第2组:
public static IEnumerable<UserProfile> CreateUsers()
{
yield return new UserProfile() {
UserId =
Guid.Parse("02cd1e9f-5947-4b08-9616-5b4f4033d074"),
UserName = "john"
};
}
public static IEnumerable<Journal> CreateJournals(UserProfile userProfile)
{
yield return new Journal() { UserProfile = userProfile };
}
您对Set2中收益率回报率不起作用的原因有何看法?
谢谢现在发生的事情是,因为您实际上并没有具体化列表,所以您正在创建两个UserProfile对象。如果在此行上放置断点,则可以看到:
yield return new UserProfile() { UserId = Guid.Parse("02cd1e9f-5947-4b08-9616-5b4f4033d074"), UserName = "john"};
您会注意到它被调用了两次——因此,jList函数不是获取为uList创建的原始UserProfile,而是获取一个新的UserProfile对象。现在,虽然它们具有相同的Guid,但它们在技术上并不相等,因为它们是引用类型,并且不指向同一个位置。然后,ChangeTracker会发现它们不相等,并尝试在数据库中创建两个对象,一个用于UserProfiles.Add(),第二个用于连接到您的jList,具有相同的Guid,这就是您获得错误的原因
您可以通过在Test2函数中对CreateUsers调用ToList()来修复代码,将列表具体化到内存中,以便所有内容都匹配
public static void TestSet2()
{
var uList = CreateUsers().ToList();
var jList = CreateJournals(uList.ElementAt(0));
_db.UserProfiles.Add(uList.ElementAt(0));
_db.Journals.Add(jList.ElementAt(0));
_db.Commit();
}
有关yield关键字如何工作的更多信息,请参见和Thank Mark。这让我更深入地了解了收益率返回的工作原理。如果您真的想知道收益率返回的工作原理,请使用reflector或ilspy打开dll,看看编译器对您的原始方法做了什么。
public static void TestSet2()
{
var uList = CreateUsers().ToList();
var jList = CreateJournals(uList.ElementAt(0));
_db.UserProfiles.Add(uList.ElementAt(0));
_db.Journals.Add(jList.ElementAt(0));
_db.Commit();
}