SᴇM*_*SᴇM -2 c# entity-framework
我有一个关于使用实体框架从表中选择特定列的问题。问题是,我正在使用Find()方法通过主键获取所需的表,然后从中获取一些数据。
我有一个包含大量列的表,如果我调用Find()method,它将返回该行的所有列,但是我只想使用例如来自2列的数据。
MyTable table = context.MyTable.Find(id); //Get MyTable object from context, id = primary key
string p1 = table.Prop1;
string p2 = table.Prop2;
Run Code Online (Sandbox Code Playgroud)
这将返回具有所有属性的单个对象(例如,它具有Prop1,Prop2,...,PropN)属性(如果已填充数据库)。所以我知道我可以使用匿名对象或数据传输对象(DTO),但是[question1]是否有其他(但很简单)的方法来获取特定的列?[question2]如果使用Find()(或应该使用Where()/Select())会影响性能吗?
var items = context.MyTable.Where(x => x.Id == id)
.Select(x => new
{
P1 = table.Prop1,
P2 = table.Prop2
});
Run Code Online (Sandbox Code Playgroud)
这将转换为sql调用,例如:
SELECT p.Prop1, p.Prop2 FROM mytable p WHERE p.Id = id
Run Code Online (Sandbox Code Playgroud)
另一种选择是将类投影回其自身,并仅提供所需的列。
var table = context.MyTable.Where(mt => mt.Id == id)
.Select(mt => new MyTable
{
Prop1 = mt.Prop1,
Prop2 = mt.Prop2
})
.FirstOrDefault();
string p1 = table.Prop1;
string p2 = table.Prop2;
Run Code Online (Sandbox Code Playgroud)
实际上,您无需创建/维护另一个类即可获得 DTO 的强类型。所有未指定的列都将使用该列类型的默认值进行填充。
它在 SQL 中转换为以下内容:
SELECT TOP(1) m.Prop1, m.Prop2 FROM MyTable m WHERE m.Id = @id
Run Code Online (Sandbox Code Playgroud)
Find()与假设您没有指定所有列相比,这确实可以提高性能。
编辑:正如 Gert 提到的,请谨慎使用,因为传递“部分实体”时并不总是显而易见。
使用数据传输对象: DTO,这是一种推荐的微软模式。
简单来说,它们只是保存数据的对象。
然后像有人建议的那样做:
public class MyDto
{
public string Prop1 {get;set;} = String.Empty
public string Prop2 {get;set;} = String.Empty
}
MyDto x = new MyDto();
x = context.MyTable.Where(x => x.Id == id)
.Select(x => new MyDto
{
P1 = table.Prop1
//I don't want prop 2, for example
});
Run Code Online (Sandbox Code Playgroud)
并绕过对象。设置自动属性(C# 6及更高版本)的默认值并仅初始化您想要的属性。
编辑:我读过你不想使用匿名和 DTO,那么你想怎么做。您可以使用对象或匿名。
其他方法只是构建一个分层结构并在需要的地方直接调用查询方法。模式存在是有原因的。
您可以调用针对动态对象的查询。有了这些,您可以分配将在运行时解析的字段,代价是失去强类型。
您可能还想检查使用动态是否具有性能价值。