我有一个类 ReportConfigurationManager 管理针对 UserReport 实体的 CRUD 操作。感兴趣的两个操作是“Get”和“SaveUpdate”。在这两种情况下,我都将操作包装在 using 语句中,以便在查询结束时处理 DbContext。
现在这些方法最终将成为 WCF 服务的一部分,但它们也可以在服务内部调用。我目前的困难在于获得一组直接调用 ReportConfigurationManager 的单元测试。
我可以创建一个新的 UserReport 并保存它(这花了我一段时间来解决,因为该实体有几个已经存在于数据库中的嵌套对象 - 我需要在调用 Add 之前将每个对象依次“附加”到上下文中UserReport 以使其正确保存。
我现在的问题是更新。
尽管有
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;
在使用 ReportConfigurationManager 的所有方法上,当我附加 UserReport 时,它以经典的“ObjectStateManager 中已经存在具有相同键的对象”失败(我认为禁用更改跟踪是为了处理这个问题?)。
所以现在我已经切换到使用我在这里找到的以下代码
public UserReport SaveUpdateUserReport(UserReport userReport)
{
using (var context = new ReportDataEF())
{
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;
if (userReport.Id > 0)
{
{
UserReport oldReport = context.UserReports.Where(ur => ur.Id == userReport.Id).FirstOrDefault();
context.Entry(oldReport).CurrentValues.SetValues(userReport);
}
}
else
{
//Need to attach everything to prevent EF trying to create duplicates in the database
context.ReportTopTypes.Attach(userReport.ReportTopType);
context.ReportWindows.Attach(userReport.ReportWindow);
context.ReportSortOptions.Attach(userReport.ReportSortOption);
foreach (var col in userReport.ReportColumnGroups)
{
context.ReportColumnGroups.Attach(col);
}
context.ReportTemplates.Attach(userReport.ReportTemplate);
//just add the new data
context.UserReports.Add(userReport);
}
context.SaveChanges();
}
return userReport;
}
我担心我的代码看起来很费力——我需要先获取旧对象的副本,然后才能保存更新的副本?我也不相信我的保存新逻辑。
那么这种方法是否正确,或者是否有更好的方法来编写上述内容?
其他事情的进一步细节:
因为我将通过 WCF 发送对象图。我已经实现了急切加载:
public static DbQuery<ReportTemplate> IncludeAll(this DbQuery<ReportTemplate> self)
{
return self
.Include("ReportColumnGroups.ReportColumns.ReportColumnType")
.Include("ReportColumnGroups.ReportColumnType")
.Include("ReportSortOptions.ReportSortColumns.ReportColumn.ReportColumnType")
.Include("ReportSortOptions.ReportSortColumns.ReportSortType");
}
public static DbQuery<UserReport> IncludeAll(this DbQuery<UserReport> self)
{
return self
.Include("ReportTemplate")
.Include("ReportTopType")
.Include("ReportWindow")
.Include("ReportSortOption.ReportSortColumns.ReportColumn.ReportColumnType")
.Include("ReportSortOption.ReportSortColumns.ReportSortType")
.Include("ReportColumnGroups.ReportColumns.ReportColumnType")
.Include("ReportColumnGroups.ReportColumnType");
}
public static DbQuery<ReportSortOption> IncludeAll(this DbQuery<ReportSortOption> self)
{
return self
.Include("ReportSortColumns.ReportColumn.ReportColumnType")
.Include("ReportSortColumns.ReportSortType");
}
public static DbQuery<ReportColumnGroup> IncludeAll(this DbQuery<ReportColumnGroup> self)
{
return self
.Include("ReportColumn.ReportColumnType")
.Include("ReportColumnType");
}
public static DbQuery<ReportColumn> IncludeAll(this DbQuery<ReportColumn> self)
{
return self
.Include("ReportColumnType");
}
public static DbQuery<ReportSortColumn> IncludeAll(this DbQuery<ReportSortColumn> self)
{
return self
.Include("ReportColumn.ReportColumnType")
.Include("ReportSortType");
}
我有一组静态的缓存数据,如下所示:
using (var context = new ReportDataEF())
{
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;
reportConfigurationData = new ReportingMetaData()
{
WatchTypes = context.WatchTypes.ToList(),
ReportTemplates = context.ReportTemplates.IncludeAll().ToList(),
ReportTopTypes = context.ReportTopTypes.ToList(),
ReportWindows = context.ReportWindows.ToList(),
ReportSortOptions =
context.ReportSortOptions.IncludeAll().ToList()
};
}
我检索 UserReports 如下:
public UserReport GetUserReport(int userReportId)
{
using (var context = new ReportDataEF())
{
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;
var visibleReports =
context.UserReports.IncludeAll().Where(ur => ur.Id == userReportId).FirstOrDefault();
return visibleReports;
}
}
我关心的测试从数据库中获取现有的 UserReport,使用静态数据类中的对象更新其 ReportTemplate 和 ReportColumnGroups 属性,然后尝试保存更新的 UserReport。
使用 Ladislav 的答案中的代码,当我尝试附加 UserReport 时,这会失败,大概是因为我附加到它的对象之一已经存在于数据库中。