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 Core 2.0/2.1-如何有效处理大型、不常访问的列?_Entity Framework_Entity Framework Core_Ef Core 2.0 - Fatal编程技术网

Entity framework EF Core 2.0/2.1-如何有效处理大型、不常访问的列?

Entity framework EF Core 2.0/2.1-如何有效处理大型、不常访问的列?,entity-framework,entity-framework-core,ef-core-2.0,Entity Framework,Entity Framework Core,Ef Core 2.0,我的表格如下: CREATE TABLE MyTable ( ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(50) NOT NULL, LARGEBLOB VARBINARY(MAX) NULL ) CREATE TABLE MyTable ( ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(50) NOT NULL, LARGEBLOBID INT NULL ) CREATE TABLE

我的表格如下:

CREATE TABLE MyTable
(
  ID INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL, 
  LARGEBLOB VARBINARY(MAX) NULL
)
CREATE TABLE MyTable
(
  ID INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL, 
  LARGEBLOBID INT NULL
)

CREATE TABLE MySubTable
(
  ID INT PRIMARY KEY,
  LARGEBLOB VARBINARY(MAX) NOT NULL
)
实体定义为:

public class Entity
{
  public int Id {get;set;}
  public string Name {get;set;}
  public virtual byte[] LargeBlob {get;set;}
}
我99%的用例只涉及显示ID和名称

1%的时间我需要大号的

有没有办法将LargeBlob标记为延迟加载,以避免 大量浪费的数据传输?或者,是否还有其他的解决方法 实现同样的结果?

我尝试拆分成两个具有1->[0 | 1]关系的表,如下所示:

CREATE TABLE MyTable
(
  ID INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL, 
  LARGEBLOB VARBINARY(MAX) NULL
)
CREATE TABLE MyTable
(
  ID INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(50) NOT NULL, 
  LARGEBLOBID INT NULL
)

CREATE TABLE MySubTable
(
  ID INT PRIMARY KEY,
  LARGEBLOB VARBINARY(MAX) NOT NULL
)
与实体

public class Entity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual LargeBlob LargeBlob { get; set; }
}

public class LargeBlob
{
    public int Id { get; set; }
    public virtual byte[] Blob { get; set; }
}
就延迟加载而言,这确实有效,但我尝试了各种各样的反向关系/外键标记,HasOne、OwnsOne、OnDelete(Cascade)在各种组合中,但我无法实现我想要实现的。简单回顾一下,这将是:

  • 只有当LargeBlob属性实际解除防护时,才会加载Blob
  • 如果entity.LargeBlob属性设置为新的LargeBlob,则会从数据库中删除(现在是“孤立的”)旧LargeBlob
  • 如果实体被删除,则相关的大blob将被删除
  • 快速更新:版本和c

    注意:我正在使用VS2017 15.6.2、.net core 2.0和EF core 2.1(以至少获得一些延迟加载的可能性)。Nuget软件包:

    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="2.1.0-preview1-final" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.0-preview1-final" PrivateAssets="All" />
    
    
    
    我尝试拆分成两个具有1->[0 | 1]关系的表,如下所示

    但是,通过将FK放入
    实体
    中,实际上实现了相反的-[0 | 1]>1关系

    要获得所需的关系,FK必须位于
    LargeBlog
    。它可以是一个单独的属性(列),但最合适的方法是使用
    Id
    属性作为PK和FK(所谓的共享PK关联)。您可以使用以下fluent配置执行此操作:

    modelBuilder.Entity<Entity>()
        .HasOne(e => e.LargeBlob)
        .WithOne()
        .HasForeignKey<LargeBlob>(e => e.Id);
    
    modelBuilder.Entity<Entity>().ToTable("MyTable");
    modelBuilder.Entity<LargeBlob>().ToTable("MyTable");
    
    modelBuilder.Entity()
    .HasOne(e=>e.LargeBlob)
    .WithOne()
    .HasForeignKey(e=>e.Id);
    
    一旦您这样做了,因为这样做的全部目的是获得单独的可控(可用时是渴望的、显式的或懒惰的)加载行为,因此可以看出,实际上并不需要单独的表——“实体”可以使用将包含blob数据的嵌入到同一个表中,只需将以下内容添加到上述配置中即可实现:

    modelBuilder.Entity<Entity>()
        .HasOne(e => e.LargeBlob)
        .WithOne()
        .HasForeignKey<LargeBlob>(e => e.Id);
    
    modelBuilder.Entity<Entity>().ToTable("MyTable");
    modelBuilder.Entity<LargeBlob>().ToTable("MyTable");
    
    modelBuilder.Entity().ToTable(“MyTable”);
    modelBuilder.Entity().ToTable(“MyTable”);
    

    请注意,虽然最合乎逻辑的选择似乎是owned type,但不幸的是,当前owned type总是被加载(类似于EF6复杂类型),因此它们不能用于实现可控的加载行为。

    您应该只选择需要节省带宽的列:

    var entity = await dbContext.Entities
      .Where(...)
      .Select(e => new
      {
        Id = e.Id,
        Name = e.Name,
        LargeBlob = null,
      })
      .FirstOrDefaultAsync();
    
    当您真正需要
    LargeBlob
    列时,手动加载它

    entity.LargeBlob = await dbContext.Entities
      .Where(e => e.Id == entity.Id)
      .Select(e => e.LargeBlob)
      .SingleOrDefaultAsync();
    
    您可以在不加载整个实体的情况下删除实体,只需Id(以及并发令牌,如果实体上存在的话)即可


    对于.NETCore,您所做的是一个很好的策略。具有已删除级联的一个应该可以做到这一点。什么是你不能做到的呢?(没有,目前还没有延迟加载,但2.1将引入其中一些功能)1。我能够做到。我并没有实际测试,但我很确定这会起作用。2是我没有工作的那个。当我设置Entity.LargeBlob=new LargeBlob()时,旧的大blob保留在表中。关于2.1,我实际上正在使用它,将编辑问题。另外,我将尝试@Ivan Stoev的答案……是的,我专注于延迟加载,而忘记了表拆分选项。他的回答很好,没什么可补充的:)