Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在实体框架中处理DbContext后使用DB对象_C#_.net_Entity Framework - Fatal编程技术网

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加载的信息比您实际需要的要多。

您自己测试过吗?谢谢,它似乎按照您上面描述的方式工作