Entity Framework "Include" 不加载实体相关表
Entity Framework "Include" does not load entity related tables
我有一个 ASP.NET Core 3.1 使用 Visual Studio 2019(64 位)和 SQL Server 2019 的项目。当我 运行 后端时,它会生成错误当我使用 Entity Framework 的 .Include
从相关的 table 加载数据时。奇怪的是,相同的代码在 Visual Studio 2017 中使用 ASP.NET Core 2.1 没有问题。在我使用 .Include
从相关的 [=82] 加载数据的每种方法中,我都会遇到这种情况=].
下图是我运行后端时产生的错误:
这是我使用 .Include
:
的方法
namespace Sistema.Web.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ArticulosController : ControllerBase
{
private readonly DbContextSistema _context;
public object Articulos { get; private set; }
public ArticulosController(DbContextSistema context)
{
_context = context;
}
[HttpGet("[action]")]
public async Task<IEnumerable<ArticuloViewModel>> Listar()
{
var articulo = await _context.Articulos.Include(a=>a.categoria).ToListAsync();
return articulo.Select(a => new ArticuloViewModel
{
idarticulo = a.idarticulo,
idcategoria = a.idcategoria,
categoria = a.categoria.nombre,
codigo = a.codigo,
nombre = a.nombre,
stock = a.stock,
precio_venta = a.precio_venta,
descripcion = a.descripcion,
condicion = a.condicion
});
}
private bool ArticuloExists(int id)
{
return _context.Articulos.Any(e => e.idarticulo == id);
}
}
}
这是主体的实体table(文章):
namespace Sistema.Entidades.Almacen
{
public class Articulo
{
public int idarticulo { get; set; }
[Required]
public int idcategoria { get; set; }
public string codigo { get; set; }
[Required]
public string nombre { get; set; }
[Required]
public decimal precio_venta { get; set; }
[Required]
public int stock { get; set; }
[StringLength(256)]
public string descripcion { get; set; }
public bool condicion { get; set; }
public Categoria categoria { get; set; }
}
}
这是相关 table(类别)的实体:
namespace Sistema.Entidades.Almacen
{
public class Categoria
{
public int idcategoria { get; set; }
[Required]
public string nombre { get; set; }
[StringLength(256)]
public string descripcion { get; set; }
public bool condicion { get; set; }
public ICollection<Articulo> articulos { get; set; }
}
}
这是 Articulo
的映射 class:
namespace Sistema.Datos.Mapping.Almacen
{
public class ArticuloMap : IEntityTypeConfiguration<Articulo>
{
public void Configure(EntityTypeBuilder<Articulo> builder)
{
builder.ToTable("articulo")
.HasKey(a => a.idarticulo);
}
}
}
这是 Categoria
的映射 class:
namespace Sistema.Datos.Mapping.Almacen
{
public class CategoriaMap : IEntityTypeConfiguration<Categoria>
{
public void Configure(EntityTypeBuilder<Categoria> builder)
{
builder.ToTable("categoria")
.HasKey(c => c.idcategoria);
builder.Property(c => c.nombre)
.HasMaxLength(50);
builder.Property(c => c.descripcion)
.HasMaxLength(256);
}
}
}
这是 DbContext
,其中包含我的 ArticuloMap
和 CategoriaMap
:
namespace Sistema.Datos
{
public class DbContextSistema : DbContext
{
public DbSet<Categoria> Categorias { get; set; }
public DbSet<Articulo> Articulos { get; set; }
public DbSet<Rol> Roles { get; set; }
public DbSet<Usuario> Usuarios { get; set; }
public DbSet<Persona> Personas { get; set; }
public DbSet<Ingreso> Ingresos { get; set; }
public object Entry(object articulos)
{
throw new NotImplementedException();
}
public DbSet<DetalleIngreso> DetalleIngresos { get; set; }
public DbSet<Venta> Ventas { get; set; }
public DbSet<DetalleVenta> DetalleVentas { get; set; }
public DbContextSistema(DbContextOptions<DbContextSistema> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new CategoriaMap());
modelBuilder.ApplyConfiguration(new ArticuloMap());
modelBuilder.ApplyConfiguration(new RolMap());
modelBuilder.ApplyConfiguration(new UsuarioMap());
modelBuilder.ApplyConfiguration(new PersonaMap());
modelBuilder.ApplyConfiguration(new IngresoMap());
modelBuilder.ApplyConfiguration(new DetalleIngresoMap());
modelBuilder.ApplyConfiguration(new VentaMap());
modelBuilder.ApplyConfiguration(new DetalleVentaMap());
}
}
}
这是 articulo
和 categoria
的数据库 table 设计以及请求的数据库关系:
.NET Core 3.1 有什么变化吗?是否需要更改或调整以解决此问题?非常感谢您的回复!
编辑:
- 替换了源代码的图像。
- 添加了相关 table
Categoria
. 实体的源代码
- 添加了映射源代码 class
CategoriaMap
.
- 添加了数据库 table 设计和关系的图像。
对于只使用图像而不是源代码制作 post,我提前表示歉意。感谢您的回复,我希望最后的编辑能更清楚地解决问题。
有多种方法可以告诉 EF 如何建立关系。默认情况下,您的对象:
//principal
public class Categoria
{
public int idcategoria { get; set; }
...
public ICollection<Articulo> articulos { get; set; }
}
//dependent
public class Articulo
{
public int idarticulo { get; set; }
public int idcategoria { get; set; }
...
public Categoria categoria { get; set; }
}
EF 将能够看到这些是相关的,因为一个文章有一个类别,一个类别有很多文章,所以它可以推断出 1:M 关系的结构。在猜测依赖链接到主体的哪一列时,它会尝试:
- categoriaidcategoria(斜体->依赖导航属性名称)
- 类别编号
- Categoriaidcategoria(斜体 -> 主体 class 姓名)
- 类别编号
最重要的是,它不再(自 3.0 起)尝试在两个具有相同名称的 class 之间找到一对属性,我认为这就是它之前工作的原因
如果您的命名约定是典型的英语,它会找到它,但根据这些规则,它不会找到西班牙风格的名称,因此您必须明确,可能最简单的方法是在关系(EF 不关心哪个)——我认为任何一种方式的论据都是可以接受的:
- 如果您在依赖项中执行此操作,那么您将在同一个 class 中引用 属性,因此您不必查看另一个 class/open 另一个文件检查它指的是什么
- 如果你在主体中这样做,那么你就是在描述 this class 中的 属性 如何链接到 属性 那 class
看起来像:
//principal
public class Categoria
{
public int idcategoria { get; set; }
...
[ForeignKey("idcategoria")] //it means Articulo.idcategoria is the relevant property that links to PK of this class
public ICollection<Articulo> articulos { get; set; }
}
或
//dependent
public class Articulo
{
public int idarticulo { get; set; }
public int idcategoria { get; set; }
...
[ForeignKey("idcategoria")] //it means idcategoria proerty above is the relevant property that links to PK property of Categoria
public Categoria categoria { get; set; }
}
我想只要选择你更喜欢的那个,并保持一致。 MSDN 中的示例使用 dependent
我有一个 ASP.NET Core 3.1 使用 Visual Studio 2019(64 位)和 SQL Server 2019 的项目。当我 运行 后端时,它会生成错误当我使用 Entity Framework 的 .Include
从相关的 table 加载数据时。奇怪的是,相同的代码在 Visual Studio 2017 中使用 ASP.NET Core 2.1 没有问题。在我使用 .Include
从相关的 [=82] 加载数据的每种方法中,我都会遇到这种情况=].
下图是我运行后端时产生的错误:
这是我使用 .Include
:
namespace Sistema.Web.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ArticulosController : ControllerBase
{
private readonly DbContextSistema _context;
public object Articulos { get; private set; }
public ArticulosController(DbContextSistema context)
{
_context = context;
}
[HttpGet("[action]")]
public async Task<IEnumerable<ArticuloViewModel>> Listar()
{
var articulo = await _context.Articulos.Include(a=>a.categoria).ToListAsync();
return articulo.Select(a => new ArticuloViewModel
{
idarticulo = a.idarticulo,
idcategoria = a.idcategoria,
categoria = a.categoria.nombre,
codigo = a.codigo,
nombre = a.nombre,
stock = a.stock,
precio_venta = a.precio_venta,
descripcion = a.descripcion,
condicion = a.condicion
});
}
private bool ArticuloExists(int id)
{
return _context.Articulos.Any(e => e.idarticulo == id);
}
}
}
这是主体的实体table(文章):
namespace Sistema.Entidades.Almacen
{
public class Articulo
{
public int idarticulo { get; set; }
[Required]
public int idcategoria { get; set; }
public string codigo { get; set; }
[Required]
public string nombre { get; set; }
[Required]
public decimal precio_venta { get; set; }
[Required]
public int stock { get; set; }
[StringLength(256)]
public string descripcion { get; set; }
public bool condicion { get; set; }
public Categoria categoria { get; set; }
}
}
这是相关 table(类别)的实体:
namespace Sistema.Entidades.Almacen
{
public class Categoria
{
public int idcategoria { get; set; }
[Required]
public string nombre { get; set; }
[StringLength(256)]
public string descripcion { get; set; }
public bool condicion { get; set; }
public ICollection<Articulo> articulos { get; set; }
}
}
这是 Articulo
的映射 class:
namespace Sistema.Datos.Mapping.Almacen
{
public class ArticuloMap : IEntityTypeConfiguration<Articulo>
{
public void Configure(EntityTypeBuilder<Articulo> builder)
{
builder.ToTable("articulo")
.HasKey(a => a.idarticulo);
}
}
}
这是 Categoria
的映射 class:
namespace Sistema.Datos.Mapping.Almacen
{
public class CategoriaMap : IEntityTypeConfiguration<Categoria>
{
public void Configure(EntityTypeBuilder<Categoria> builder)
{
builder.ToTable("categoria")
.HasKey(c => c.idcategoria);
builder.Property(c => c.nombre)
.HasMaxLength(50);
builder.Property(c => c.descripcion)
.HasMaxLength(256);
}
}
}
这是 DbContext
,其中包含我的 ArticuloMap
和 CategoriaMap
:
namespace Sistema.Datos
{
public class DbContextSistema : DbContext
{
public DbSet<Categoria> Categorias { get; set; }
public DbSet<Articulo> Articulos { get; set; }
public DbSet<Rol> Roles { get; set; }
public DbSet<Usuario> Usuarios { get; set; }
public DbSet<Persona> Personas { get; set; }
public DbSet<Ingreso> Ingresos { get; set; }
public object Entry(object articulos)
{
throw new NotImplementedException();
}
public DbSet<DetalleIngreso> DetalleIngresos { get; set; }
public DbSet<Venta> Ventas { get; set; }
public DbSet<DetalleVenta> DetalleVentas { get; set; }
public DbContextSistema(DbContextOptions<DbContextSistema> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new CategoriaMap());
modelBuilder.ApplyConfiguration(new ArticuloMap());
modelBuilder.ApplyConfiguration(new RolMap());
modelBuilder.ApplyConfiguration(new UsuarioMap());
modelBuilder.ApplyConfiguration(new PersonaMap());
modelBuilder.ApplyConfiguration(new IngresoMap());
modelBuilder.ApplyConfiguration(new DetalleIngresoMap());
modelBuilder.ApplyConfiguration(new VentaMap());
modelBuilder.ApplyConfiguration(new DetalleVentaMap());
}
}
}
这是 articulo
和 categoria
的数据库 table 设计以及请求的数据库关系:
.NET Core 3.1 有什么变化吗?是否需要更改或调整以解决此问题?非常感谢您的回复!
编辑:
- 替换了源代码的图像。
- 添加了相关 table
Categoria
. 实体的源代码
- 添加了映射源代码 class
CategoriaMap
. - 添加了数据库 table 设计和关系的图像。
对于只使用图像而不是源代码制作 post,我提前表示歉意。感谢您的回复,我希望最后的编辑能更清楚地解决问题。
有多种方法可以告诉 EF 如何建立关系。默认情况下,您的对象:
//principal
public class Categoria
{
public int idcategoria { get; set; }
...
public ICollection<Articulo> articulos { get; set; }
}
//dependent
public class Articulo
{
public int idarticulo { get; set; }
public int idcategoria { get; set; }
...
public Categoria categoria { get; set; }
}
EF 将能够看到这些是相关的,因为一个文章有一个类别,一个类别有很多文章,所以它可以推断出 1:M 关系的结构。在猜测依赖链接到主体的哪一列时,它会尝试:
- categoriaidcategoria(斜体->依赖导航属性名称)
- 类别编号
- Categoriaidcategoria(斜体 -> 主体 class 姓名)
- 类别编号
最重要的是,它不再(自 3.0 起)尝试在两个具有相同名称的 class 之间找到一对属性,我认为这就是它之前工作的原因
如果您的命名约定是典型的英语,它会找到它,但根据这些规则,它不会找到西班牙风格的名称,因此您必须明确,可能最简单的方法是在关系(EF 不关心哪个)——我认为任何一种方式的论据都是可以接受的:
- 如果您在依赖项中执行此操作,那么您将在同一个 class 中引用 属性,因此您不必查看另一个 class/open 另一个文件检查它指的是什么
- 如果你在主体中这样做,那么你就是在描述 this class 中的 属性 如何链接到 属性 那 class
看起来像:
//principal
public class Categoria
{
public int idcategoria { get; set; }
...
[ForeignKey("idcategoria")] //it means Articulo.idcategoria is the relevant property that links to PK of this class
public ICollection<Articulo> articulos { get; set; }
}
或
//dependent
public class Articulo
{
public int idarticulo { get; set; }
public int idcategoria { get; set; }
...
[ForeignKey("idcategoria")] //it means idcategoria proerty above is the relevant property that links to PK property of Categoria
public Categoria categoria { get; set; }
}
我想只要选择你更喜欢的那个,并保持一致。 MSDN 中的示例使用 dependent