如何在代码优先实体框架中使用视图


87

我如何首先在实体框架代码中使用数据库视图,


2
以下所有答案均未说明如何使用EF迁移创建视图。有关类似问题,请参见此答案
Rudey

这是一个完全相同的问题的线程。- stackoverflow.com/questions/13593845/...
股利蒂瓦里

试试我的解决方案。它阻止了标记为视图的表的迁移生成
kogoia

Answers:


95

如果像我一样,您仅对映射来自其他数据库的实体(在我的情况下为erp)感兴趣,以将它们与应用程序特定的实体相关联,则可以像使用表一样使用视图(在以同样的方式!)。显然,如果您尝试更新该实体,则如果视图不可更新,则会出现异常。该过程与普通(基于表)实体的情况相同:

  1. 为视图创建POCO类;例如FooView
  2. 在DbContext类中添加DbSet属性
  3. 使用FooViewConfiguration文件为视图设置其他名称(在构造函数中使用ToTable(“ Foo”);)或设置特定的属性

    public class FooViewConfiguration : EntityTypeConfiguration<FooView>      
    {
        public FooViewConfiguration()
        {
            this.HasKey(t => t.Id);
            this.ToTable("myView");
        }
    }
    
  4. 将FooViewConfiguration文件添加到modelBuilder中,例如,检查Context的OnModelCreating方法:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new FooViewConfiguration ());
    }
    

64
+1(不假设“代码优先” ==自动生成数据库)
onetwopunch 2012年

3
@DaveJellison您是否愿意详细说明,或提供一个将视图添加为IDatabaseInitializer的一部分的链接
拉尔夫·希灵顿

18
是我一个人,还是每个人都在通过迁移创建空表?有办法避免这种情况吗?
Kremena Lalova 2015年

4
只需确保在这里,此解决方案是否需要我们预先在外部SQL数据库上创建View?是否可以在代码中定义视图,并通过Add-Migration / Update-Database命令将其填充到数据库中?
frostshoxx

6
一些东西。1.此答案未提及您必须使用SQL手动创建视图,这可以通过迁移来完成。2.如果类名与视图名称匹配,则不必配置视图名称。3.您可以像这样使用DataAnnotations [Table("myView")],这可以说比使用创建一个更简单EntityTypeConfiguration
Rudey

23

这可能是一个更新,但是要首先使用带有EF Code的视图,只需将[Table(“ NameOfView”)]添加到类的顶部,所有这些都应该正常工作,而不必经历其他所有人正在经历的所有麻烦。同样,您将不得不将其中一列报告为[key]列。这是我下面的实现示例代码。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace SomeProject.Data
{
    [Table("SomeView")]
    public class SomeView
    {
        [Key]
        public int NameID { get; set; }
        public string Name { get; set; }
    }
}

这是上下文的样子

using System.Data.Entity;

namespace SomeProject.Data
{
    public class DatabaseContext : DbContext
    {
        public DbSet<SomeView> SomeViews { get; set; }
    }
}

2
这与接受的答案相同,除了它使用DataAnnotations时,接受的答案使用EF Fluid API。
Rudey

4
其实不,不是。我尝试了接受的答案,但没有成功,但对我来说效果不佳。但是随后我正在使用迁移,因此这可能会对事情产生影响。我发现我必须先进行迁移,然后添加我的视图类,因为它已经存在于数据库中。如果数据库中已有表,我们将以完全相同的方式处理它。由于视图是“虚拟表”,因此实体框架中的表语法仍然有效。
Charles Owen

11

如果您想要的只是一堆非规范化的对象,那么您可能只是在类中创建了一个公共的get-onlyIQueryable<TDenormolized>属性DbContext

在中,get您将返回Linq结果,以将反标准化的值投影到反标准化的对象中。这可能比编写数据库视图更好,因为您正在编程,而不仅限于使用select语句。而且它是编译时类型安全的。

请注意,不要触发枚举之类的ToList()调用,因为它们会打断延迟的查询,您最终可能会从数据库中获得一百万条记录,并在应用程序服务器上对其进行过滤。

我不知道这是否是正确的方法,但我尝试过并且对我有用。


6
我想使用视图的原因之一是EF生成的SQL并不总是“不错”的-我们的模型中有一些继承层次结构(发现陷阱太晚了...),使用视图可以使我们手动创建SQL。关于为什么观点会更好的一个对立点
卡尔

2
不这样做的其他原因可能是使用了递归公用表表达式,这在LINQ中不可用。否则,这对于较简单的方案是一个很好的建议。
汤姆·帕索里克(TomPažourek)'16

1
如果要利用索引视图的优点,则不能使用属性代替视图。
Rudey

“您不仅限于使用select语句”。这是什么意思 您可以使用SELECT语句完成对LINQ的任何处理,而对于其他方法则不能这样说。
Rudey

3

我知道这是一个老问题,并且这里有很多答案,但是当我使用答案时我被迫提出问题,并且在Package Manager控制台中使用update-database命令时发生了错误:

数据库中已经有一个名为“ ...”的对象。

并且我使用以下步骤来解决此问题:

  1. 在Package Manager控制台中运行以下命令:Add-migration intial
  2. 在Migrations文件夹下,您可以找到..._ intial.cs文件,将其打开并注释或删除与要映射的类相关的任何命令
  3. 现在,您通常可以使用update-database命令对模型进行任何其他更改

希望能帮助到你。


1
谢谢!这真的有帮助!另外,您不仅可以删除EF迁移生成的代码,还可以在其中添加migrationBuilder.Sql("CREATE OR REPLACE VIEW ...);这样同事也可以使用它来升级他们的数据库。
Rich_Rich
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.