如果想在Code first中使用数据库里的视图
(不管你出于什么原因),目前的方法有2种。
var query = db.Database.SqlQuery<ReplyStatusViewModel>("SELECT * FROM dbo.vReplyStatus")
然后在vReplyStatus视图的基础上进行各种查询:
var qqo = query.Where(p => p.PrdOrd.Contains("袁")); var count = qqo.Count();//会出错!-->nullreferenceexception-->因为PrdOrd字段里有null或空值。
改为如下可通过:
var qqo = query.Where(p => p.PrdOrd != null && p.PrdOrd.Contains("袁"));
这样产生的语句是:
SELECT * FROM dbo.vReplyStatus.Where(p => ((p.PrdOrd != null) AndAlso p.PrdOrd.Contains("袁")))
但是在使用到dynamic linq时好像无法把p.ProdOrd != null 加上,dynamic linq产生的语句是:
SELECT * FROM dbo.vReplyStatus.Where(p => p.Planner.Contains("袁")).Union(SELECT * FROM dbo.vReplyStatus.Where(p => p.PrdOrd.Contains("袁"))).Union(SELECT...
这是一个模糊查询语句,在所有的字段中查找包含袁的数据。但是少了!=null 的条件,这样在计数的时候var count = qqo.Count();就会出错。
现在使用的是第二种方法,将ReplyStatusViewModel类加入上下文类中,然后在model创建时加入该实体(把视图假装是一个表)。提示数据迁移后,先不要update-database!把迁移文件中的内容注释掉,即把 public override void Up() 和 public override void Down()的内容清空,来进行一次空的迁移,最后更新数据库。
步骤如下:
1、创建类(ReplyStatusViewModel)该类和视图中的字段一一对应。
public class ReplyStatusViewModel { public int ID { get; set; } public bool Del { get; set; } public decimal? Qty { get; set; } public string ReplyStatus { get; set; } }
2、更改上下文类
public class MyContext : DbContext
{ public MyContext () : base("name=DefaultConnection") { } public DbSet<ReplyStatusViewModel> ReplyStatusViewModel { get; set; }// 映射数据库里的视图 protected override void OnModelCreating(DbModelBuilder modelBuilder) {
// vReplyStatus 就是视图的名字 modelBuilder.Entity<ReplyStatusViewModel>().ToTable("vReplyStatus"); } }
3、添加数据迁移
PM> Add-migration test
会自动显示一个类文件,把上下文里的更改当做创建一个表:
public partial class test : DbMigration { public override void Up() { CreateTable( "dbo.ReplyStatusViewModels", c => new { ID = c.Int(nullable: false, identity: true), Del = c.Boolean(nullable: false), Qty = c.Decimal(precision: 18, scale: 2), ReplyStatus = c.String(), }) .PrimaryKey(t => t.ID); } public override void Down() { DropTable("dbo.ReplyStatusViewModels"); } } }
这里的内容不是我们需要的,如果数据库里还没有视图,可以在up里创建一个视图:
public override void Up() { Sql(@"CREATE VIEW [dbo].[vReplyStatus] AS SELECT a.ID, …… "); } public override void Down() { Sql(@"IF EXISTS
(SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'dbo.vReplyStatus')) DROP VIEW dbo.vReplyStatus"); }
如果数据库里已有视图,则把内容清空即可:
public override void Up() { } public override void Down() { }
添加数据迁移时可以加一个参数:IgnoreChanges,这样Up和Down里自动为空白。
最后运行
PM> Update-Database
在Controller里可以像使用其他实体类一样来使用视图了!
public string GetMasterData() { using (var db = new PurchasePlanContext()) { IQueryable<ReplyStatusViewModel> query9 = db.ReplyStatusViewModel; query9 = from m in query9 where m.PrdOrd.Contains("袁") select m; var count9 = query9.Count(); ... } }
http://stackoverflow.com/questions/13593845/how-to-create-a-view-using-ef-code-first-poco
http://stackoverflow.com/questions/20862807/mapping-database-views-to-ef-5-0-code-first-w-migrations?rq=1
http://msdn.microsoft.com/zh-cn/magazine/dn519921.aspx
这里提到一个CreateView方法,可惜我没有找到!
public partial class AddView : DbMigration { public override void Up() { this.CreateView("dbo.CasinosWithOver100SlotMachines", @"SELECT * FROM Casino.Casinos WHERE Id IN (SELECT CasinoId AS Id FROM Casino.SlotMachines GROUP BY CasinoId HAVING COUNT(CasinoId)>=100)"); } public override void Down() { this.RemoveView("dbo.CasinosWithOver100SlotMachines"); } }
--End--