C# 在实体框架中处理DbContext后使用DB对象
在实体框架中处理C# 在实体框架中处理DbContext后使用DB对象,c#,.net,entity-framework,C#,.net,Entity Framework,在实体框架中处理DbContext后,我是否仍可以使用从DbContext检索到的对象 例如: class partial DBUser { public string Username { get; set; } } DBUser myUser; using (var context = new DbContext()) { myUser = context.Users.First(); } // does the following code work? string
DbContext
后,我是否仍可以使用从DbContext
检索到的对象
例如:
class partial DBUser
{
public string Username { get; set; }
}
DBUser myUser;
using (var context = new DbContext())
{
myUser = context.Users.First();
}
// does the following code work?
string username = myUser.Username;
我想它仍然可以使用,但是在处理DbContext
之前未加载的任何字段(惰性计算)都不会返回任何结果。我说得对吗
我知道理想情况下应该将用户名分配给using语句中的一个变量,但我只是好奇…对于简单成员,它可以工作,但是如果您访问不急于加载的相关成员(导航属性),您将得到一个异常,即DbContext已被释放 例如:
public class Order
{
public int OrderId { get; set; }
public string OrderNumber { get; set; }
public virtual Customer Customer { get; set; }
}
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
}
Order order = null;
using (var context = new AppDbContext())
{
order = context.Orders.Find(orderId);
}
var orderNumber = order.OrderNunber; // Ok.
var customerName = order.Customer.Name; // Not Ok.
为了让客户满意,您需要知道如何将客户与订单一起加载:
Order order = null;
using (var context = new AppDbContext())
{
order = context.Orders
.Include(x => x.Customer)
.Single(x => x.OrderId == orderId);
}
var orderNumber = order.OrderNunber; // Ok.
var customerName = order.Customer.Name; // Ok.
需要注意的是,要知道需要包括哪些相关实体。这也是低效的,因为对于使用Include
的较大实体和实体图,这实际上是从查询/w联接生成选择*,以返回受影响表中的所有数据
通常,利用Select
将实体投影到所需的适用数据结构中效率更高。例如,如果您只需要给定OrderID的OrderNumber
string orderNumber = null;
using (var context = new AppDbContext())
{
orderNumber = context.Orders
.Where(x => x.OrderId == orderId)
.Select(x => x.OrderNumber)
.Single();
}
或者,如果您需要订单号和客户名称:
string orderNumber = null;
string customerName = null;
using (var context = new AppDbContext())
{
var orderDetails = context.Orders
.Where(x => x.OrderId == orderId)
.Select(x => new { x.OrderNumber, CustomerName = x.Customer.Name })
.Single();
orderNumber = orderDetails.OrderNumber;
customerName = orderDetails.CustomerName;
}
通常在投影时,您将创建一个ViewModel或DTO类,用选择或利用Automapper的ProjectTo
方法而不是匿名类型来填充。这里的好处是,生成的SQL只需执行一个SELECT o.OrderNumber,c.Name FROM Orders o internal JOIN Customers c ON…
语句,而不是从联接表中选择所有列。投影时,不需要加载相关实体。(无包含语句)
作为一般规则,我建议不要将实体传递到从中读取的DbContext范围之外。EF确实支持分离实体并将其重新附加到其他DBContext,但这种技术容易增加复杂性和错误,而且最终从DB加载的信息比您实际需要的要多。您自己测试过吗?谢谢,它似乎按照您上面描述的方式工作