【问题标题】:HasDbFunction, table value function without a mapped entity classHasDbFunction,没有映射实体类的表值函数
【发布时间】:2022-08-20 04:20:25
【问题描述】:

到目前为止我发现的所有内容,如果您正在调用表值函数,则返回值必须是 IQueryable。例如:

public IQueryable<AlbumsByGenre> ufn_AlbumsByGenre_ITVF(int genreId)
    => FromExpression(() => ufn_AlbumsByGenre_ITVF(genreId));

大多数情况下,当我使用表值函数时,返回的表类型是 DTO。也就是说,它与数据库中的任何实际表都不匹配。这是一个例子:

CREATE FUNCTION dbo.ufn_AlbumsByGenre_ITVF(@GenreId int)
RETURNS TABLE
AS
RETURN(  
    SELECT 
      ar.ArtistName,
      al.AlbumName,
      g.Genre
    FROM Genres g 
      INNER JOIN Albums al
        ON g.GenreId = al.GenreId 
      INNER JOIN Artists ar 
        ON al.ArtistId = ar.ArtistId
    WHERE g.GenreId = @GenreId
);

为返回类型创建实体会导致数据库中出现不必要的、未使用的和不需要的表。在本例中,表名是“AlbumsByGenre”。

有没有办法让返回类型成为未映射的类型以防止不必要的表?

  • 仅当您使用迁移时,该表才会添加到数据库中。它没有在那里,因为 EF 永远不会尝试直接查询它。我认为您甚至可以将其从生成的迁移脚本中删除(没有尝试,我尽量避免迁移)。

标签: c# entity-framework-core ef-core-6.0


【解决方案1】:

目前(从 EF Core 6.0 开始)该类型必须是模型类型(带或不带键)。有针对 EF Core 7.0 的 Raw SQL queries for unmapped types 计划,它可能允许也可能不允许您要求的映射。

所以现在你的类型必须在模型中注册(不能取消映射)。但是创建关联表不是强制性的,可以通过使用ToView(null) 配置来避免,例如

modelBuilder.Entity<AlbumsByGenre>()
    .HasNoKey() // keyless
    .ToView(null); // no table or view

【讨论】:

  • 呵呵,当然!让我再次微笑:)
【解决方案2】:

是的,只需创建一个具有ArtistNameAlbumNameGenre 的类,但它不应该是IQueryable,而只是List&lt;AlbumsByGenre&gt;IEnumerable&lt;AlbumsByGenre&gt;ICollection

IQueryable 是用于表或视图的延迟查询构建器。

SQL 函数结果无法在 SQL Server 中进一步查询,因此只需删除 IQueryable

【讨论】:

  • 我不遵循这个答案。 IQueryable 是定义表值函数的正确方法,请参阅 documentation
  • @ChineSyndrome 你不太明白我担心的问题。他们不想要模型中的强制性映射类。
  • 他们使用动态类型 = 动态
  • DbContext.FromExpression<TResult> 方法返回 IQueryable<TResult> 并要求 TResult 是实体类型。如果您知道从 EF Core 调用 DB 函数的其他方式,请提供代码示例。
  • 他们使用动态类型——我跟不上。无论如何,TVF 返回一个表(因此得名),因此该函数必须返回某种可枚举类型。它是IQueryable,因为与您所说的相反,结果是可组合的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 2014-10-21
  • 2013-03-04
相关资源
最近更新 更多