我正在处理的项目中有很多相互关联的实体,我正在使用WCF在几个客户端应用程序中使用它们.我很快就意识到每次调用我都会在数据库中序列化一半的数据.我修复了当前的问题,但系统仍在进行大量的数据库调用,因为我的服务层对象遍历其构造函数中数据层中的所有嵌套对象.很多时候这是完全没必要的,所以我开始考虑替代方案.
如果我指定我的嵌套属性的Id,那么除非我访问嵌套对象的属性,否则我不相信数据库调用.
public class MyDataObject
{
public Guid Id { get; set; }
public string SomeProperty { get; set; }
public Guid NestedDataObjectId { get; set; }
[ForeignKey("NestedDataObjectId")]
public virtual NestedDataObject NestedDataObject { get; set; }
}
然后我可以使用我的服务对象的构造函数来确定是否延迟加载嵌套对象,如下所示:
public class MyServiceObject
{
public MyServiceObject(MyDataObject myDataObject,
bool includeNested = true)
{
Id = myDataObject.Id;
SomeProperty = myDataObject.SomeProperty;
NestedServiceObjectId = myDataObject.NestedDataObjectId;
if (includeNested)
NestedServiceObject = new NestedServiceObject(myDataObject.NestedDataObject,
includeNested);
}
}
哪个工作正常,除了现在我的单元测试的模拟数据库上下文存在问题,因为我必须将对象和id添加到每个模拟DbSet,因为我更改了服务代码以使用NestedObjectId属性而不是NestedObject.Id属性
所以我想知道我访问的唯一虚拟属性是否仍然是Id字段,如果它仍然会对整个对象进行数据库调用.就像是
if (includeNested)
{
NestedServiceObject = new NestedServiceObject(myDataObject.NestedDataObject);
}
else
{
NestedServiceObject = new NestedServiceObject(myDataObject.NestedDataObject.Id);
}
这将解决我的模拟问题,因为服务代码总是引用NestedObject.Id属性,无论编码和维护的简易性,我最终都会这样做,但我很好奇这是否是这个是正确的方法.
最佳答案 这里的主要问题是您的服务API会导致数据访问层流失.您的服务模型非常密切地重新组合您的数据访问模型,因此很难声明特定方法需要哪些数据以及可以省略哪些数据.
我建议重新设计您的服务API,以便每个服务方法都接受最小的输入参数集并返回最小的输出参数集.
您很可能必须为每个服务方法引入请求和响应对象.这并不意味着您不能在不同方法中重用任何模型.您必须识别仅在一起使用时才有意义的数据,并将它们作为单独的类提取.
然后,在每种服务方法中,您只能检索创建响应所需的数据.您可以通过定义EF数据投影并将它们手动映射到响应对象或使用AutoMapper等库来实现.
例如:
var result = db.Students
.Select(x => new { Id = x.Id, FacultyName = x.Faculty.Name})
.FirstOrDefault(x => x.Id == studentId);
如果你写这样的东西,EF实际上足够聪明,只能查询所需的数据.