.Net Core 3.x无主键实体类型避免创建表

17

我需要在Entity Framework Core 3.1.1中执行一条复杂的SQL查询,经过研究,我发现键控实体类型是代码优先方法的正确选择。我看到了很多关于DBQuery的文档,但是这在.NET Core 3.x中已经被标记为过时。

键控实体类型

根据Microsoft文档的说法,它表示dbquery已经过时,因此请改用dbset方法,但是使用dbset方法会尝试在数据库中创建新表。如何在应用迁移时禁用键控实体类型中的表生成?

示例代码

public class ApplicationContext : DbContext
{
 public DbSet<CustomQuery> CustomQuery { get; set; }
 protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
    modelBuilder.Ignore<CustomQuery>();
    modelBuilder.Entity<CustomQuery>().HasNoKey();
 }
}

使用 .NET Core 2.2

var entity = _context.Query<CustomQuery>().FromSqlRaw(Regex.Unescape(selectQuery)).AsNoTracking().FirstOrDefault();

使用 .NET Core 3.1

var newEntity = _context.CustomQuery.FromSqlRaw(Regex.Unescape(selectQuery)).AsNoTracking().FirstOrDefault();
如果我尝试应用迁移,那么会创建一个名为“custom query”的新表,但是我不需要这种情况发生。因为这只是一个用于保存联接查询值的模型,我不会在此表中插入、更新或删除值。如何实现这一点?或者是否有更好的方法来处理这种情况?

你的查询是动态的还是静态的? - Getson Cela
它是动态查询。 - Richard Vinoth
1
不幸的是,Ef Core 3.x 有一些限制。我们有两个选项来映射我们的查询: 1-将查询结果映射到实体(每个表)。 2-在数据库中创建一个视图,然后将自定义对象映射到该视图。也许第二个选项更好,可以解决问题,以便映射您的自定义类型而无需创建表。 - Getson Cela
非常感谢,也许现在我会与我们的团队内部讨论并决定是继续使用过时的代码(不可接受),还是转向视图概念。 - Richard Vinoth
2个回答

22
这是EF Core 3中已知的缺陷,在这里报告:3.0 Upgrade - Entity with HasNoKey() (formerly a query type) tries to create tables when adding migration #18116。它被视为To vs From methods: Proposal to rationalize ToTable, ToQuery, ToView, FromSql, and other related methods #17270Ability to exclude/skip/ignore parts of the model from migrations so that a table is not created (for overlapping bounded contexts) #2725的“重复”,并计划在5.0发布时解决。
目前的解决方法在EF Core团队成员的评论中提到:

For now, you can just use something like .ToView("You forgot to use FromSql with ModQueueEntry")

或者更普遍地说,使用.ToView(null),例如:
modelBuilder.Entity<CustomQuery>().HasNoKey().ToView(null);

我之前确实使用过ToView,但我不知道你可以传递null这种hack。很有趣。 - Jackal
对我来说使用KeylessAttribute修复了这个问题。 - 0xBADF00D
1
@0xBADF00D 是的,KeylessAttribute在efcore 5.0中引入,对于之前的版本,我们必须使用答案中提供的.ToView(null)。请查看 https://learn.microsoft.com/en-us/ef/core/modeling/keyless-entity-types?tabs=data-annotations 中的第一个注释。 - prinkpan

0

在进行 .net core 迁移时,如果要从代码优先方法中排除模型/类/实体,请参考此处。例如,复杂类型类用于映射存储过程结果。在进行迁移时,我们不想在数据库中创建复杂的类型表,则应将其从迁移中排除。

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Ignore<PMEDetail>();
            modelBuilder.Entity<PMEDetail>().ToTable(nameof(PMEDetail), t => t.ExcludeFromMigrations());
            modelBuilder.Entity<PMEDetail>(entity => entity.HasNoKey());  
        }

这里的PMEDetail类是一个复杂类型的类,在OnModelCreating中排除迁移。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接