【问题标题】:How to create a view using EF code-first POCO如何使用 EF 代码优先 POCO 创建视图
【发布时间】:2012-11-15 15:23:37
【问题描述】:

就这么简单。我需要使用 Code First 创建一个 View。我在谷歌和 SO 上都没有发现任何关于这个的信息。有没有办法做到这一点?

我需要使用 linq 创建和查询该视图,因此在创建数据库时使用脚本创建它不是解决方案,例如:

var results = from c in db.Customer
join v in db.MyView on c.Id equals v.Id
select c;

解决方法也是可以接受的。我需要一种针对非常量/非实体值查询实体的方法。

【问题讨论】:

  • 创建视图:创建一个 sql 视图,就像您编写一个实体并在 SQL 上将其翻译为表一样。

标签: c# linq entity-framework ef-code-first


【解决方案1】:

您必须手动创建视图,就像 AnatoliiG 所说的那样。 (Adding index to a table)。

您将视图的名称作为属性添加到您的类中

[Table("UserDTO")]
    public class UserDTO
{
    /* Class code here */
}

您可以通过在末尾指定 -IgnoreChanges 属性来创建空迁移

Add-Migration MigrationName -IgnoreChanges

这为您提供了一个可以手动修改的空迁移脚本。

您可以使用您的数据库上下文在迁移脚本中执行您的代码

public partial class editUserDTO : DbMigration
{
    public override void Up()
    {
        string script =
        @"
        CREATE VIEW dbo.UserDTO
        AS SELECT p.PersonId AS UserId, p.FirstName, p.LastName, u.UserName
        FROM dbo.Users u
        INNER JOIN dbo.People p ON u.PersonId = p.PersonId";
        BloggingContext ctx = new BloggingContext();
        ctx.Database.ExecuteSqlCommand(script);
    }

    public override void Down()
    {
        BloggingContext ctx = new BloggingContext();
        ctx.Database.ExecuteSqlCommand("DROP VIEW dbo.UserDTO");
    }
}

【讨论】:

  • 不应该CREATE 应该只在Up() 中,而DROP 应该只在Down() 中吗?
  • 您好...尝试更正我在这篇文章中编写的代码(从“Down”方法中删除了 ctx.Database.ExecuteSqlCommand(script);)但被 3 个用户拒绝。
  • 你可以使用继承自DbMigrationSql(...)函数,而不是创建上下文并调用ctx.Database.ExecuteSqlCommand
  • -IgnoreChanges 忽略的更改不会显示在下一次添加的迁移中吗?
  • 可能缺少步骤,但我必须在“添加迁移”步骤之前将新视图类的 Dbset 添加到 DbContext。此外,在编辑空迁移脚本以实现视图的添加和删除后,我必须手动删除视图并运行“更新数据库”以确保我没有在脚本中出错并完成迁移/数据库更新对。
【解决方案2】:

请注意,在 EF 6.1(不确定是否更早)中,您现在可以使用 Code First from Database 选项,它也将映射到视图。

我个人在一个单独的垃圾项目中拥有我的,所以我可以从中取出我想要的代码,而不会影响我实际使用数据库的项目。使用它Add a New file to your project -> Data -> ADO.NET Entity Data Model

然后选择Code First From Database 选项并选择您的视图(如果需要,还可以选择其他表格)

它将像 Fred 在他的回答中所说的那样将其创建为表映射,但会为您完成所有代码,这很好。不过,您可能希望更改索引和排序。

然后只需在您的Up 中调用Sql(@"YOUR VIEW CREATE SQL HERE") 并在您的Down 中添加Sql(@"DROP STATEMENT HERE")

【讨论】:

    【解决方案3】:

    official issues thread of EF7 提供了很多很好的见解:

    1) 没有 DbSet,而是有一个属性或扩展方法

    A) 属性

    class YourContext
    {
        public IQueryable<YourView> YourView 
        {
            get
            {
                return this.Database.SqlQuery<YourView>("select * from dbo.YourView");
            }
        }
    }
    

    B) 扩展方法

    static class YourContextExtensions
    {
        public static IQueryable<YourView>(this YourContext context)
        {
            return context.Database.SqlQuery<YourView>("select * from dbo.YourView");
        }
    

    2) 显然,您可以让迁移过程忽略某些数据库集

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      if (IsMigration)
        modelBuilder.Ignore<YourViewTable>();
     ...
    }
    

    (以上均未经测试)

    【讨论】:

    • 一个点不起作用Cannot implicitly convert type 'Syste.Data.Entity.Infrastructure.DbRawSqlQuery .. to ...&lt;model&gt;你必须将IQueryable改为IEnumerable
    • 大头钉,在sqlquery函数后可以查询到最后
    • 不,不要在SqlQuery 之后链接AsQueryable。这不会为您提供动态查询对象。当按照建议使用SqlQuery 时,将选择所有记录并将其加载到内存中,即使代码使用Where 过滤它们或使用FirstOrDefault...参见this answer
    • 解决方案 2 已在此处测试并运行。我使用stackoverflow.com/a/31102959/1291428 作为设置 isMigration 标志的灵感。
    • @Todd B 无法编译,您是从哪里设法在静态类中获得“this”而不在方法签名中的? =]
    【解决方案4】:

    您无法使用 EF Code First 方法创建视图。如果要创建视图,请在 Seed 方法中执行创建 sql 脚本。但是您仍然无法将实体映射到此视图,除非通过创建和删除与您的视图具有相同名称的表来破解模型。

    一些有用的链接:

    【讨论】:

    • 这是一个缺乏想象力的答案。早在 2012 年就可能有变通办法。请务必查看其他答案。
    • SqlGenerator w/ Table Annotations 有人吗?奇怪的答案。
    • 什么是“种子法”?
    【解决方案5】:

    您无法从 EF Code First 创建视图,您应该在“种子”脚本中添加脚本以预填充视图。

    【讨论】:

    • 嗨!请修改您的答案,因为它实际上并没有回答 OP 的问题,而只是表明 OP 想要做的事情无法完成。如果您需要帮助,请查看帮助部分中的how to answer
    • 我认为这不属于种子方法。创建视图应在 EF 迁移中完成。
    • 这个答案和this one from four years previous一样。
    猜你喜欢
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 2011-07-03
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    相关资源
    最近更新 更多