Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
Entity framework 在紧急加载时,是否可以排除EF中的反向导航属性?_Entity Framework_Navigation Properties - Fatal编程技术网

Entity framework 在紧急加载时,是否可以排除EF中的反向导航属性?

Entity framework 在紧急加载时,是否可以排除EF中的反向导航属性?,entity-framework,navigation-properties,Entity Framework,Navigation Properties,在EF6中使用.Include语法时,始终会加载反向导航属性。有没有办法把它关掉?下面是一个示例查询 private static IQueryable<Account> GetAccountsEager(this IRepository<Account> repository) { return repository .Queryable() .Include(e => e.AccountLocations

在EF6中使用.Include语法时,始终会加载反向导航属性。有没有办法把它关掉?下面是一个示例查询

private static IQueryable<Account> GetAccountsEager(this IRepository<Account> repository)
{
    return repository
        .Queryable()
        .Include(e => e.AccountLocations
            .Select(l => l.Address.City.State.Country));
}
但是,如果我添加这样一个include:

return repository.Queryable()
    .Include(e => e.BillToAddress.AddressType)
    .Include(e => e.BillToAddress.City.State.Country);
    .Include(e => e.AccountLocations.Select(a => a.Address.City.State.Country));
然后为e.BillToAddress.City和每个AccountLocation的Address.City加载反向导航地址。为什么在第三个包含中添加.Select会影响第二个包含

下面是SQL: 其他信息: 以下是DbContextConfiguration:

public DataContext(string nameOrConnectionString)
    : base(nameOrConnectionString)
{
    _instanceId = Guid.NewGuid();
    Configuration.LazyLoadingEnabled = false;
    Configuration.ProxyCreationEnabled = false;
}
以下是执行查询的方法(使用.FirstOrDefault()):

公共静态帐户(
这个IRepository存储库,
int id)
{
var query=repository.GetQueryableEager();
返回query.FirstOrDefault(e=>e.AccountId==id);
}
这是一座城市:

public partial class City: Entity, IDatabaseMetaData
{
    public int CityId { get; set; } // CityId (Primary key)
    public string CityName { get; set; } // CityName
    public int StateId { get; set; } // StateId
    public DateTime InsertDatetime { get; set; } // InsertDatetime
    public int InsertSystemUserId { get; set; } // InsertSystemUserId
    public DateTime? UpdateDatetime { get; set; } // UpdateDatetime
    public int? UpdateSystemUserId { get; set; } // UpdateSystemUserId
    public int? CountyId { get; set; } // CountyId

    // Reverse navigation
    public virtual ICollection<Address> Addresses { get; set; } // Address.FK_Address_CityId

    // Foreign keys
    public virtual County County { get; set; } // FK_City_CountyId
    public virtual State State { get; set; } // FK_City_StateId

    public City()
    {
        InsertDatetime = System.DateTime.Now;
        Addresses = new List<Address>();
        InitializePartial();
    }

    partial void InitializePartial();
}
公共部分类城市:实体,IDatabaseMetaData
{
public int CityId{get;set;}//CityId(主键)
公共字符串CityName{get;set;}//CityName
public int StateId{get;set;}//StateId
公共日期时间InsertDatetime{get;set;}//InsertDatetime
public int InsertSystemUserId{get;set;}//InsertSystemUserId
公共日期时间?UpdateDatetime{get;set;}//UpdateDatetime
public int?UpdateSystemUserId{get;set;}//UpdateSystemUserId
公共int?CountyId{get;set;}//CountyId
//反向导航
公共虚拟ICollection地址{get;set;}//Address.FK_Address_CityId
//外键
公共虚拟县{get;set;}//FK_City_CountyId
公共虚拟状态状态{get;set;}//FK_City_StateId
公共城市()
{
InsertDatetime=System.DateTime.Now;
地址=新列表();
初始化部分();
}
部分无效初始化部分();
}

我认为你看到的是“关系修复”的结果:

关系修复可确保在第二个实体进入ObjectContext时自动链接相关对象


在您的情况下,由于您包括
AccountLocation.Address.City
,EF正在加载您请求的相关
Address
实体和相关
City
实体,并作为“修复”的一部分它将加载的
地址
实体添加到
城市导航集合中,这些实体将是
城市
->
地址
一对多关系的一部分

你可以在上找到另一个例子。与您的情况一样,延迟加载和代理创建也被禁用——但是,该链接不包括禁用此行为的方法

在紧急加载时,是否可以排除EF中的反向导航属性

没有

正如在另一个答案中所解释的,EF有一个关系修复过程,将它加载到上下文中的所有实体编织在一起。你不能以任何方式停止这个过程。因此,如果您不亲自处理事情,您将永远拥有这个臃肿的Json字符串。(我无法解释或再现您似乎发现的负载差异,但这应该是一个新问题的主题。我不会指望它们总是发生,希望它们能解决您当前的问题)

这就是关键所在:控制局面。这取决于你的情况,什么是最好的策略,但有几个选择

  • 将查询投影到匿名类型并将其序列化为JSON。这只是一个简单的例子:

    repository.Queryable()
              .Select(e => new 
              {
                   Account = e.Name,
                   AccountLocations = 
                       e.AccountLocations
                        .Select(l => new
                        {
                            Address = new { l.Address.Street, l.Address.Number },
                            City = l.Address.City.Name,
                            Country = l.Address.City.Country.Name,
                        })
              });
    
    有些人会反对从方法返回匿名类型,即使它是JSON格式的,但对我来说,它只是一个以某种所需格式返回JSON的方法。它只会让非类型化JavaScript世界更近一步

  • 对命名类型(DTO,或视图模型,类型)的结构执行相同的操作

  • 创建一个没有双向关联的专用上下文。这是一个经常被遗忘的选项,但为什么总是要有一个上下文来访问数据?只需确保上下文使用(或生成)的类与属于主上下文的类具有不同的名称


  • 顺便说一句,通过这样做,您还可以根据需要对从数据库中获取的数据量进行定制。

    您说:因此,它会重新加载所有反向导航地址,以提供比查询中所需数据多得多的数据。我是否可以以某种方式关闭反向导航?您确定生成的SQL正在返回更多数据吗可能SQL查询很好,EF只填充反向导航属性,这应该不会有问题。是的,查询提取的数据比我想要的要多。如果我得到一个城市为达拉斯的帐户,它会返回城市的反向导航属性(地址),因此包含达拉斯的每个地址都会返回“后加载”。您可以发布由第二条语句生成的sql查询。如果有剩余的连接来获取地址,或者只有内部连接。我按照建议编辑了帖子,以包含EF为第二条查询生成的sql。为什么您需要这些导航属性来保持不被填充?
    public DataContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
        _instanceId = Guid.NewGuid();
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }
    
    public static Account GetEager(
        this IRepository<Account> repository,
        int id)
    {
        var query = repository.GetQueryableEager();
    
        return query.FirstOrDefault(e => e.AccountId == id);
    }
    
    public partial class City: Entity, IDatabaseMetaData
    {
        public int CityId { get; set; } // CityId (Primary key)
        public string CityName { get; set; } // CityName
        public int StateId { get; set; } // StateId
        public DateTime InsertDatetime { get; set; } // InsertDatetime
        public int InsertSystemUserId { get; set; } // InsertSystemUserId
        public DateTime? UpdateDatetime { get; set; } // UpdateDatetime
        public int? UpdateSystemUserId { get; set; } // UpdateSystemUserId
        public int? CountyId { get; set; } // CountyId
    
        // Reverse navigation
        public virtual ICollection<Address> Addresses { get; set; } // Address.FK_Address_CityId
    
        // Foreign keys
        public virtual County County { get; set; } // FK_City_CountyId
        public virtual State State { get; set; } // FK_City_StateId
    
        public City()
        {
            InsertDatetime = System.DateTime.Now;
            Addresses = new List<Address>();
            InitializePartial();
        }
    
        partial void InitializePartial();
    }
    
    repository.Queryable()
              .Select(e => new 
              {
                   Account = e.Name,
                   AccountLocations = 
                       e.AccountLocations
                        .Select(l => new
                        {
                            Address = new { l.Address.Street, l.Address.Number },
                            City = l.Address.City.Name,
                            Country = l.Address.City.Country.Name,
                        })
              });