如何告诉 EF / DbSet 附加到 SQL 视图而不是尝试创建同名的表?

发布于 2024-10-24 13:13:35 字数 2833 浏览 1 评论 0原文

我想使用 Code-First 的 DropCreateDatabaseAlwaysDropCreateDatabaseIfModelChanges 功能,因为我围绕该功能构建了许多集成测试。有没有比创建表、删除表,然后使用 sql 命令创建视图更优雅的方式附加到 SQL 视图?

[使用 VS2010 Professional、ASP.NET 4、MVC3、EF4、SQL Server 2008 R2 Express、Win7]

public MyContext : DbContext {
    public DbSet<Person> Persons {get; set;}
    public DbSet<Worker> Workers {get; set;}
    public DbSet<Signin> Signins {get; set;}
    public DbSet<SigninView> SigninView {get; set;}
}
public class Person
{   
    public int ID { get; set; }
    public virtual Worker Worker { get; set; }
}
public class Worker
{
    public int ID { get; set; }
    public int barcodenumber {get; set;}
    public virtual Person Person { get; set; }
    public virtual ICollection<WorkerSignin> workersignins { get; set; }
}
public class WorkerSignin
{
    public int ID { get; set; }
    public virtual Worker worker {get; set;}
    public int barcodenumber {get; set;}
}

Person.ID == Worker.ID。它们是 1 到 0..1 的关系。总会有一个人;可能没有工人记录。

public class PersonBuilder : EntityTypeConfiguration<Person>
{
    public PersonBuilder()
    {
        ToTable("Persons");
        HasKey(k => k.ID);
        HasOptional(p => p.Worker).WithRequired().WillCascadeOnDelete();
    }
}
public class WorkerBuilder : EntityTypeConfiguration<Worker>
{
    public WorkerBuilder() 
    {
        HasKey(k => k.ID);
        HasMany(s => s.workersignins)
            .WithOptional(s => s.worker)
            .HasForeignKey(s => s.WorkerID);
    }
}

登录表接收来自条形码扫描仪的输入。工作人员刷卡并登记当天。 客户端要求记录登录,即使扫描时 Worker 表中没有相应的记录。由于客户端的要求,我计划使用一个我可以控制的 ID主键,并以编程方式或尽可能与视图关联条形码编号。

SigninView 结合了 Person、Worker 和 Signin 表中的信息,以显示在刷 ID 的网页上。我假设 SQL Server 视图比关联 3 个表数据的 C# 视图更快。 (我觉得我没有时间停下来测试这个)。

所以...我想做的是附加到视图。我可以使用 DbSet<> 附加到视图,但在开发应用程序时,我还使用 CodeFirst 重新创建表结构。

现在我遇到了一个问题,Code-First 创建了一个表 SigninView,然后删除它并使用 SqlCommands 创建视图:

public class MyInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{

    protected override void Seed(MyContext myDB)
    {
        myDB.Database.SqlCommand(@"drop table machete.dbo.WorkerSigninView");
        myDB.Database.SqlCommand(@"CREATE VIEW [dbo].[WorkerSigninView]
                                        AS
                                        SELECT dbo.WorkerSignins.ID, dbo.WorkerSignins.barcodenumber
                                        FROM   dbo.Persons INNER JOIN
                                               dbo.Workers ON dbo.Persons.ID = dbo.Workers.ID RIGHT OUTER JOIN
                                               dbo.WorkerSignins ON dbo.Workers.barcodenumber = dbo.WorkerSignins.barcodenumber"); 
    }

I would like to to use Code-First's DropCreateDatabaseAlways and DropCreateDatabaseIfModelChanges functionality because I built a number of integration tests around the feature. Is there a more elegant want to attach to an SQL view than creating the table, dropping the table, and then creating the view with the sql command?

[Using VS2010 Professional, ASP.NET 4, MVC3, EF4, SQL Server 2008 R2 Express, Win7]

public MyContext : DbContext {
    public DbSet<Person> Persons {get; set;}
    public DbSet<Worker> Workers {get; set;}
    public DbSet<Signin> Signins {get; set;}
    public DbSet<SigninView> SigninView {get; set;}
}
public class Person
{   
    public int ID { get; set; }
    public virtual Worker Worker { get; set; }
}
public class Worker
{
    public int ID { get; set; }
    public int barcodenumber {get; set;}
    public virtual Person Person { get; set; }
    public virtual ICollection<WorkerSignin> workersignins { get; set; }
}
public class WorkerSignin
{
    public int ID { get; set; }
    public virtual Worker worker {get; set;}
    public int barcodenumber {get; set;}
}

Person.ID == Worker.ID. They're in a 1 to 0..1 relationship. There will always be a person; there may not be a worker record.

public class PersonBuilder : EntityTypeConfiguration<Person>
{
    public PersonBuilder()
    {
        ToTable("Persons");
        HasKey(k => k.ID);
        HasOptional(p => p.Worker).WithRequired().WillCascadeOnDelete();
    }
}
public class WorkerBuilder : EntityTypeConfiguration<Worker>
{
    public WorkerBuilder() 
    {
        HasKey(k => k.ID);
        HasMany(s => s.workersignins)
            .WithOptional(s => s.worker)
            .HasForeignKey(s => s.WorkerID);
    }
}

The Signin table receives input from a barcode scanner. Workers swipe a card and register for the day. The client requires that the the Signin be recorded even if there's no corresponding record in the Worker table at the time of the scan. Because of the client requirement, I am planning on using an ID I can control as the primary key, and correlate the barcodenumber programmatically or with a view where possible.

The SigninView combines information from the Person, Worker, and Signin tables to present on the webpage where the ID is getting swiped. I'm assuming that an SQL server view will be faster a view than my C# correlating 3 tables worth of data. (I don't feel I have time to stop and test this).

So...what I want to do is attach to the View. I can attach to the view using DbSet<>, but I'm also using CodeFirst to re-create my table structure as I develop the application.

Right now I have a kludge where Code-First creates a table SigninView, then dropping it and creating the view with SqlCommands:

public class MyInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{

    protected override void Seed(MyContext myDB)
    {
        myDB.Database.SqlCommand(@"drop table machete.dbo.WorkerSigninView");
        myDB.Database.SqlCommand(@"CREATE VIEW [dbo].[WorkerSigninView]
                                        AS
                                        SELECT dbo.WorkerSignins.ID, dbo.WorkerSignins.barcodenumber
                                        FROM   dbo.Persons INNER JOIN
                                               dbo.Workers ON dbo.Persons.ID = dbo.Workers.ID RIGHT OUTER JOIN
                                               dbo.WorkerSignins ON dbo.Workers.barcodenumber = dbo.WorkerSignins.barcodenumber"); 
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

压抑⊿情绪 2024-10-31 13:13:35

Code First 目前不支持数据库视图,因此如果您想使用重新创建数据库,您必须使用您的方法、带有投影到数据类型的自定义 linq 查询(这是常见方法)或 SqlQuery 来直接执行您的 SELECT。

Code first currently doesn't have support for database views so If you want to use recreate databese you must use either your approach, custom linq query with projection to data type (that is common approach) or SqlQuery to execute your SELECT directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文