How can I tell EF / DbSet to attach to an SQL View and not try to create a table with the same name?
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.开发者_StackOverflow社区 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");
}
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.
精彩评论