Scott Hanselman

Simple Code First with Entity Framework 4 - Magic Unicorn Feature CTP 4

July 15, '10 Comments [54] Posted in ASP.NET | ASP.NET MVC | Data | IIS
Sponsored By

Space Needle made of LEGOMicrosoft's been releasing a number of right-sized LEGO pieces lately. In case you missed it, Betas have been announced for:

  • SQL 4 Compact Edition - It has a small embedded file-based SQL Database, and a web-server called IIS Express that's compatible with the full version of IIS.
  • "Razor" Page Syntax - A way to make pages/ViewEngine called "Razor." Your sites can be later be expanded to use all of ASP.NET MVC. It's a simple syntax that is easy to learn.
  • WebMatrix - It's a small (15 megs if you have .NET 4, 50megs if you don't) lightweight IDE for making ASP.NET or PHP websites. Good for non-pro developers.
    • It uses the WebDeploy engine to deploy apps to hosts, setting up permissions, copying databases, etc.
    • WebMatrix also has the free Search Engine Optimization Toolkit built in, so you can spider your own site and see how Search Engines see it. It'll make recommendations and store reports.
  • IIS Express - A version of the IIS 7.5 Web Server that can be run as non-admin, isn't installed as a service, that will also integrate with Visual Studio

More details to come on all this. Howver, on the tooling side, I did get a chance to talk to Damian Edwards, a developer working on some of this stuff and I put video up on Channel 9 yesterday.

There's lots of cool pieces that are packaged up with WebMatrix initially, but these pieces are interesting for pro developers as well.

Still, something's missing.

imageIn my mind, it's been too hard to talk to databases. I like LINQ to SQL and used it on the first NerdDinner version, but since EF4 sucks so much less is way better than earlier versions of EF, Jon and I updated NerdDinner to use EF. It was easy, but I would have liked to code first, and code only if I could.

Microsoft announced a new Entity Framework CTP today. It has the romantic and wonderful name "Microsoft ADO.NET Entity Framework Feature CTP4" which is lame. You can say "EF Feature CTP4" but I like "EF Magic Unicorn Edition" but that's just me. We're getting the tech better at Microsoft but still can't get naming right. Whadayagonnado? Still, it makes EF a pleasure.

It's got a lot of interesting features and choices, and while it's still a CTP, you should take a minute and check it out. 

To get a more detailed version of this walkthrough plus downloadable sample code, check out the ADO team's excellent blog post.

Quick CRUD via a Code First Model

After you install it (it won't mess up your system if you do), go and create a new whatever project. For my little example, I'll make a new ASP.NET MVC Website. It works for me better than a console app to illustrate a point.

Add a reference to Microsoft.Data.Entity.CTP.dll.

image

Make a new class, maybe in the Models folder, and name it something like Book. Add some code like this. Notice it's just code. Nothing derives from anything.

public class Book
{
[Key]
public int ISBN { get; set; }
[Required]
public string Title { get; set; }
public DateTime FirstPublished { get; set; }
public bool IsFiction { get; set; }
}

Notice I've put [Key] and [Required] on this class, but if that bothers me, I could put these kinds of declarations in a more fluent way in my database context class, in OnModelCreating.

builder.Entity<Book>().HasKey(b => b.ISBN);
builder.Entity<Book>().Property(b => b.Title).IsRequired();

To access my data, Here's a SimpleBookCatalog...

public class SimpleBookCatalog : DbContext
{
public DbSet<Book> Books { get; set; }
}

Next, I'll make a new Controller, via right|click Add Controller. I'll make a BookController.

public class BookController : Controller
{
SimpleBookCatalog db = new SimpleBookCatalog();

public ActionResult Index()
{
var books = db.Books;
return View(books);
}
...
}

I'll right click on the Index method and make an Index view. Then I'll run my app.

image

No data. What if I look in my SQL Management Studio? I got a Database created for me with a convention-based name since I didn't supply one.

SQL Management Studio with an automatically named Database

If I specified a different connection string, that DB could be anywhere.

However, if use a different database provider, like say, a SQL 4 Compact Edition one, setting it as the default in my Application_Start:

Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");

Then when I run my app and look in my App_Data folder:

SQL Compact Edition Database file in App_Data

So I got a file based database without doing anything and I don't need SQL Server. (Yes, I can change the name, location, etc.) If I do nothing, I get a reasonable convention.

Next, I'll add two Create methods, one for a GET and one for a POST. In Create, I'll add my new book and save the changes:

public ActionResult Create()
{
return View();
}

[HttpPost]
public ActionResult Create(Book book)
{
db.Books.Add(book);
db.SaveChanges();
return RedirectToAction("Index");
}

I'll right click, Add View, and make a Create View. Run my app, look at the empty list, then click Create.

My Create Form

Click Create, and I'm redirected back to the Index page:

Book List

Back on the Index page, I can change the link to Details to use our primary key:

<%: Html.ActionLink("Details", "Details", new { id=item.ISBN })%> |

Create a Details View and add a Details method:

public ActionResult Details(int id)
{
var book = db.Books.Find(id);
return View(book);
}

See that Find method? That's there automatically. I can certainly use al the LINQy goodness as well, but as you can see, CRUD is simple. I can hook up Edit and Delete in a few minutes as well.

Here's the whole thing:

public class BooksController : Controller
{
SimpleBookCatalog db = new SimpleBookCatalog();

public ActionResult Index()
{
var books = db.Books;
return View(books);
}

// GET: /Books/Details/5
public ActionResult Details(int id)
{
var book = db.Books.Find(id);
return View(book);
}

// GET: /Books/Create
public ActionResult Create()
{
return View();
}

[HttpPost]
public ActionResult Create(Book book)
{
db.Books.Add(book);
db.SaveChanges();
return RedirectToAction("Index");
}

// GET: /Books/Edit/5
public ActionResult Edit(int id)
{
return View(db.Books.Find(id));
}

// POST: /Books/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
var book = db.Books.Find(id);
UpdateModel(book);
db.SaveChanges();
return RedirectToAction("Index");
}

// GET: /Books/Delete/5
public ActionResult Delete(int id)
{
var book = db.Books.Find(id);
return View(book);
}

// POST: /Books/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
db.Books.Remove(db.Books.Find(id));
db.SaveChanges();
return RedirectToAction("Index");
}
}

So that's a nice simple controller that uses a model that was written in just code. The database and its schema was created for me. The DbContext is LINQable with stuff like Add, Find, and Remove all just there. Plus, it's all EF under the hood, so if you need more complex stuff, you can do it.

For example, here's a more complex Code First Model with Collections, and more attributes. I show some fluent wiring up of relationships later on, although there are conventions that can assign bi-directionality based on naming.

public class Book
{
[Key]
public int ISBN { get; set; }
[Required]
public string Title { get; set; }
[Required]
public DateTime FirstPublished { get; set; }
[Required]
public bool IsFiction { get; set; }

public virtual Publisher Publisher { get; set; }
[RelatedTo(RelatedProperty="Author")]
public virtual Author Author { get; set; }
}

public class Person
{
[ScaffoldColumn(false)]
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class Author : Person
{
[ScaffoldColumn(false)]
public int AuthorId { get; set; }

public virtual ICollection<Book> Books { get; set; }
}

public class Publisher
{
[ScaffoldColumn(false)]
public int PublisherId { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }

public virtual ICollection<Book> Books { get; set; }
}

public class SimpleBookCatalog : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<Author> Authors { get; set; }
public DbSet<Publisher> Publishers { get; set; }
}

Also, "Magic Unicorn EF" supports DataAnnotations (or validation via Fluent interfaces), so those [Required] and [StringLength] stuff from before? Those apply not only in JavaScript, but also at the Server-side and Database persistence layers.

image

You can make your own strategies for creating databases, based on what's going on with the model, if it's changed, etc. Here's some built-in examples. Yours can do whatever you like. Here the SimpleBookCatalog is the DbContext from before.

//This is the default strategy.  It creates the DB only if it doesn't exist
Database.SetInitializer(new CreateDatabaseOnlyIfNotExists<SimpleBookCatalog>());
//Recreates the DB if the model changes but doesn't insert seed data.
Database.SetInitializer(new RecreateDatabaseIfModelChanges<SimpleBookCatalog>());
//Strategy for always recreating the DB every time the app is run.
Database.SetInitializer(new AlwaysRecreateDatabase<SimpleBookCatalog>());

Connection Strings for the SQL 4 CE provider are simpler (like, they are possible to memorize, which is amazing, considering how hard they are now). For example:

<add name="SimpleBookCatalog" connectionString="Data Source=C:\FooFoo\MyBooks.sdf" providerName="System.Data.SqlServerCe.4.0"/>

Here's some examples of fluent mappings and setting up relationships to give you an idea of the kinds of things you can do, while avoiding looking at any visual designers. It all depends on how clean you need your POCO (Plain Old CLR Objects) to be.

modelBuilder.Entity<Book>().HasKey(b => b.ISBN);
modelBuilder.Entity<Book>().HasRequired(b => b.Title);
modelBuilder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.Books);
modelBuilder.Entity<Publisher>().Property(p => p.Name).MaxLength = 50;
modelBuilder.Entity<Author>().HasMany(a => a.Books).WithRequired();

These configurations can be batched up into a class that handles configuration for a specific entity so you can reuse them and more easily config like this.

builder.Configurations.Add(new BookConfiguration());

All this is a really basic example as a means of introduction and for my own learning, but so far I like it. It takes just a few minutes to get a lot done without much code. Since this is all Entity Framework, I can put an OData service on top of my model really quickly and then start consuming those services from iPhones or whatever.

It'll be interesting to take a sample like Nerd Dinner or MVC Music Store and change them to use Code First EF and the Razor View Engine and see if they are more readable and how many fewer lines of code they are.

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Thursday, July 15, 2010 2:22:27 AM UTC
It great !

Thanks
Thursday, July 15, 2010 2:36:03 AM UTC
I really like the idea of code-first, but I have two reservations/thoughts:

1) How do you manage important physical properties of the database like indexes? From what I see these would have to be managed outside the scope of the code-first specification. Yes I know some people will say that physical database design should be left up to the DBAs, but I think its not so clear cut these days. In fact I believe that sensible indexes can and should be designed a priori. I guess different persistence platforms may need different configurations physical designs as well.

2) This all starts to get into the area of "modelling" as in what they are trying to solve with SQL Server Modelling. If you define your model with c# as opposed to something higher level or more generic (e.g. "m") then are you restricting how easily you can repurpose that model? I can see this code-first+data annotations being an awesome end-to-end solutions to get something build quick and keep you brain focused on business value not keeping all the layers synchronized. But in some ways as soon as you want to step outside this scenario you will wish you had a model (or a variant of it ) that can be more easily reused. Perhaps even outside my app? I guess it is not very lean of me to consider such complications when this stuff can probably solve 90% of my requirements! So... is this all a precursor to SQL Server Modelling? I'm not sure but I suspect we are seeing a specialization of what they are trying to generalise with "m".

/braindump
Thursday, July 15, 2010 3:56:29 AM UTC
I used the previous CTP and really liked the Code first approach. There are extended methods that allow you to persist the edmx (this really just creates a runtime edmx), so it would be a decent workflow to start with code, then move to the model as the thing. I think it all points to SQL Server Modelling in the future, but my sense is that we are not yet there.
There are still some rough patches in EF 4, for me the biggest being simple support for System.Enum code types, but it is really promising.
robert schroeder
Thursday, July 15, 2010 8:35:35 AM UTC
It almost seems like a natural extension to EF, what with already being able to model data as entities why not allow the entities themselves define the structure of the underlying data store.

Jack's comment around physical properties of a DB is an interesting one, but presumably this is either a) implementation-specific and as such not something you'd necessarily concern yourself with when merely creating as data store with entity markup, or b) something that is actually supported by the Magic Unicorn feature and we've just not seen it yet.

Very interesting stuff and something I look forward to playing around with shortly.
Thursday, July 15, 2010 8:42:10 AM UTC
In fact, to follow up on Jack's query regarding physical features and my previous comment, it appears to be answered on the ADO.NET blog article:

"In CTP4 we have implemented the following conventions:
o Primary Key
o Relationship Inverse
o Foreign Key
o Pluralization of Table Names
o Support for Data Annotations

We posted details about all the Data Annotations we plan to support here The annotations supported in CTP4 are:
o Key
o StringLength
o ConcurrencyCheck
o Required
o Timestamp
o DataMember
o RelatedTo
o MaxLength
o StoreGenerated"...

EF CTP4 Released @ ADO.NET blog

(hmm - looks like Google's OpenId doesn't display your name very well here..)

Robin Osborne
Thursday, July 15, 2010 9:25:32 AM UTC
This is great!
Now please help them get IoC built into ASP.Net MVC (it's a pit of success thing) and work out a solution for managing interacting and overlapping models in our applications.
If this results in the option to do MEF-based CQRS, that would be "tha bomb", but hey, I'll settle for less to start with :-)
Dirk
Thursday, July 15, 2010 9:57:06 AM UTC
Great article, thx!
Thursday, July 15, 2010 9:59:59 AM UTC
Hey Scott,

It's been a long time coming but I really like the new injection of the good, wholesome clean technologies with a code-first (as opposed to designer first) focus.

Razor and code-first EF looks like wins.

- Demis
Thursday, July 15, 2010 10:46:56 AM UTC
Great article, thx!
Thursday, July 15, 2010 12:30:19 PM UTC
We need to rally behind this as a community. Whatever needs to be done must be done. We need a full-on Tweet-Storm and a Blog-War. The name "EF Magic Unicorn Edition" MUST STAY!
Thursday, July 15, 2010 3:02:45 PM UTC
The whole CRUD piece reminds me of groovy + grails framework.
Aditya
Thursday, July 15, 2010 3:35:28 PM UTC
@Jack

Some comments from the Microsoft Magic Unicorn team:

1. Re: where is the injection point to specify physical database artifacts like indexes
>> This is something you can do with CTP4. We'll be posting some follow-up blog posts on the ADO.NET team blog in the next week about how to customize database initialization, seed it with sample data, or do all kinds of extra goodies.

2. Re: CodeFirst's relationship with SSMoS and model re-usability
>> This is coming, but it's going to take a bit longer. We're working on defining our experience of using Code First with various kinds of tooling/designers as optional workflows. So if you don't want to go 100% code, you'll have some alternatives you can augment your app with while still being primarily code focused.

Oh, and EF + Enums. Yeah, we know. It's coming :)

Jeff
Jeff
Thursday, July 15, 2010 4:51:11 PM UTC
This is all cool, but obvious features. Why is it that it takes the EF Team forever to ship it?
Thursday, July 15, 2010 7:29:49 PM UTC
This is a bit of an aside - in the intro you say (boldfaced for emphasis):

"Razor" Page Syntax - A way to make pages/ViewEngine called "Razor." Your sites can be later be expanded to use all of ASP.NET MVC. It's a simple syntax that is easy to learn.


When I first read this it looked like you were suggesting Razor is not a full-fledged view engine, as capable as the current view engine. I had to comb through ScottGu's article until the VERY end, where he stated in the summary that:
<blockquote cite=ScottGu">You can also drop standalone .cshtml/.vbhtml files into your application and run them as single-pages – which also enables you to take advantage of it within ASP.NET Web Forms applications as well.</blockquote>

This asp/php style of programming available through Razor ought to be highlighted a bit more.
Thursday, July 15, 2010 7:31:18 PM UTC
PS! that is one strict html parser you have there... a missing attribute quote and the whole tag is invalidated...
Thursday, July 15, 2010 10:01:26 PM UTC
Does the SimpleBookContext implement IDisposable? Does it need to be disposed in your controller?
Thursday, July 15, 2010 10:18:38 PM UTC
It does implement IDisposable, and you can/should do it if you want to be really responsible. It's not a HUGE deal, but it's a valid point.
Thursday, July 15, 2010 10:52:15 PM UTC
This is everything that I had been wishing for this Christmas I just hope that I can get a RTM version before then. This is starting to be SubSonic cool but hopefully with a bit fewer bugs... So where do I go to add feature Requests?? There is just one more thing I would like to add.... If I create properties in my classes named CreatedBy/CreatedOn/ModifiedBy/ModifiedOn I want EF10 (I know you like EF Magic Unicorn but I like the idea of it skipping a lot of version numbers as it did have a lot of kinks to get worked out) to know what to do with those columns namely grab a UserName out of thin air like SubSonic does and update the Dates each time it gets saved without making me write those four lines over and over again. I can't wait to give it a try as this is what I thought it did when I first heard about Code First in EF4.
Friday, July 16, 2010 2:05:29 AM UTC
Scott,

The whole disposable aspect of the entity framework is its greatest downfall. It seems like a small thing, but I don't think entity frameworks should create disposable. I realize the actual database classes (such as SqlConnection) are disposable, and I think okay. But frameworks designed to exist up the stack shouldn't require anything that ties your hands such as IDisposable.

The ASP.NET MVC examples use an instance of the entity framework without disposing (such as the music store example).

I noticed that you mentioned that it "sucked less". EF4 doesn't suck that bad. It can be made to work. I have a basic ActiveRecord pattern being generated by T4 templates sitting on top of a very simple repository. This creates workable code that doesn't suck to work with, but it could be so much better.

The entity framework has a few fundamental problems that hopefully can be solved in future releases.

1. Disposing should not be in this framework.

2. No particular pattern. EF4 tried to be the lowest common denominator, instead of picking a particular pattern for data access it leaves that up to the user. While that is the most flexible, I believe constraints are more liberating. If EF4 forced people down a simple pattern it would be more useful and suck less.

3. Working on multiple results set at a single time can create strange exceptions. If you follow a rigid pattern when using EF4 this can be avoided, but otherwise...

Friday, July 16, 2010 7:51:50 AM UTC
scott,
hope ms can finalize this ASAP, im a hardcore, linq to sql fan,
dont like the current EF, tried (DONT LIKE IT) still love linetoSQL, altho its does a horrible job with (inner joins and sub query), my solution, well just use SP for complex queries.

but this looks very promising, as long as its

EASIER, & BETTER!

im willing...

just that i cant work with CTP, what if the final version has revision, dont have the time to re-code for LIVE system.
loooking forward to final version.. what is that????

thanks
Friday, July 16, 2010 8:00:08 AM UTC
ISBN starts out as string:

public string ISBN { get; set; }

but seems to change later to be an int, so when I added the details method, it gives a runtime error:

public ActionResult Details(int id)

Friday, July 16, 2010 8:19:06 AM UTC
I keep hearing arguments for repurposing, and how code first restricts the model, but seriously just HOW many times has anyone 'repurposed' a data layer. its the same argument for "writing a layer so we can swap out xxxx if we need to.". Simple truth is that 99.9% of the time , you'll never swap out your data layer or any other layer. If you're going to make the change from SQLServer to Oracle, or anything to anything, its usually best to worry about that when it happens.
I've been around quite a number of years, and i've *never* come across a project where we'd write stuff so we could 'repurpose' what we'd already got.

However, I'd love to see non theoretical, non trivial samples too. Just in case I'm wrong. Which I probably am.
Good work Scott. Keep it up.

Cheers,
Rob
Friday, July 16, 2010 3:36:07 PM UTC
How can you specify your own database if all you want to do is map to one, and not have it generate one? This is really frustrating because you keep showing how it can make its own, but because of how long most of us have had to keep waiting on code-first, we've had to go ahead and make systems that use the old UI designer model with existing databases.

You reference a map to ProductContext; What is ProductContext? Where is it created? Is it an ObjectContext or a DbContext? What kind of parameter are we needing so that it can accept a specified database? Etc. Etc. It'd be really nice if some of these kinds of things could be clarified.

Thanks for the information. I'm looking forward to see how Code'First' develops. I think that's a misnomer, though. I haven't spoken to a programmer yet that cared about making their database with code, just mapping to it.
Derek
Friday, July 16, 2010 4:48:15 PM UTC
Derek,
I want the database to be scripted from the model really, and code is a great way to start building the model via conventions. IMHO, T-SQL is a horrible language for database and table creation and modification. M looks to be a huge improvement and when that gets tied to EDMX, I think we will have a great way to 1) provide standard classes of functionality that can evolve (I will have many tables that always are tied to a tenant id, and always have standard columns, others that do not, but fall into a different pattern (say M2M relationships), etc.) If I can model that at the conceptual level, then I can evolve my database at the appropriate level of abstraction. Ultimately, the model should be the key, again, IMO, because it is the thing that should know about both the store and the code, and the model should be rich enough to encompass all patterns, but simple enough to make the common things easy and the unusual possible. End soap box.
robert schroeder
Friday, July 16, 2010 5:09:44 PM UTC
Derek, sorry if this post was too much of a summary. There's a LOT here and I could have dug and dug deeper. ProductContext in my little snippet was a DbContext. I'll change a few names in the post to try to make it more cohesive for future readers.

Random Google Open ID Guy - Yes, that was my mistake. ISBN should be an int. I changed it above.

Rob - Totally get you. You can pass in a regular Connection String to a DbContext derived class and, if you like, use CodeFirst (perhaps manually, perhaps via code generation) to describe an existing database.
Friday, July 16, 2010 6:30:17 PM UTC
@Derek For a bunch of people the database is just an artifact, somewhere to store the data. Many projects start that way too.

If you already have an existing database why would you want to represent it in code? There are already great tools that will generate the mapping EDMX file from a database and let you visually tweak it if needed.

[)amien
Saturday, July 17, 2010 10:19:58 PM UTC
This is great stuff! Such a big improvement.

I'm down with Magic Unicorns.

If I am using something like StuctureMap or Unity with MVC, I wonder what the best way would be to inject SimpleBookCatalog into the controller? Would it be to simply just extract an interface from it and inject ISimpleBookCatalog into the controller's constructor, or should I do something like nHibernate where you configure the session on the application start up?
Sunday, July 18, 2010 2:56:00 AM UTC
This is a good walkthrough, enough detail to see that the featureset of NHibernate + FluentnHibernate Automap is close to at parity. I would say my use of nhibernates days are now numbered. It seemed like it was just a matter of time and I am glad to see the teams that are farther down the stack helping build in the features that the smaller but loud community really digs. Good to see this coming together.
Monday, July 19, 2010 8:00:00 AM UTC
I've long had the concerns expressed so well by @Jack near the top of the comments. It's good/interesting to see from a later comment that these are/will be covered by the MMU team (I can't type that name in full!)
Wednesday, July 21, 2010 9:31:45 AM UTC
I wonder how this plays along with depdency injection and n-tier applications. When you say "Entity Framework quietly slips into the background" will the dbcontext invade my top tiers? Will I still be able to cleanly separate the layers?
Florian Hötzinger
Wednesday, July 21, 2010 9:33:55 AM UTC
Edit: You didnt actually say "Entity Framework quietly slips into the background" , Julie Lerman did and I copied my comment from there ;)
Florian Hötzinger
Wednesday, July 21, 2010 12:11:46 PM UTC
Florian,
wrt - "the dbcontext invade my top tiers? Will I still be able to cleanly separate the layers?"

As presently defaulted it is certainly possible for the dbcontext to infiltrate, but you can with work, knowledge and vigilance, cleanly separate the layers. I would not classify that as a pit of success default though.
It seems to me to be defaulting, at present, to getting something up and running for a very quick demo rather than defaulting to something that is truly architecturally sound. There has been a lot of progress on the different code generation templates, and a lot to like in the flexibility, but it is hard to get your head around what features require what when you start writing custom templates, at least in my own limited experience.
robert schroeder
Wednesday, July 21, 2010 6:11:20 PM UTC
So I was wondering, does the CTP work with the Compact 4 ?


4. Code first programming model support for Compact 4.0 in ADO.NET Entity Framework: The Microsoft ADO.NET Entity Framework Feature Community Technology Preview 3 is an early preview of the code-first programming model for the ADO.NET Entity Framework 4.0. The code-first feature in the ADO.NET Entity Framework CTP3 release does not work properly with Compact 4.0. Future releases of code-first programming model for ADO.NET Entity Framework will provide support for code-first programming model for Compact 4.0.

SQL Compact Blog
Thursday, July 22, 2010 6:17:02 PM UTC
How would you do an update to an entity using the repository pattern? Adding a new entity is still a simple call to myRepository.dbContext.Books.Add(newBook), but updating an existing one seems to involve finding the original object from the dbContext, manually changing each of the updated properties and then calling SaveChanges on the dbContext again. It seems like the framework could handle this better, much like a simple call to UpdateModel(book) in the controller.
Benjamin Rice
Friday, July 23, 2010 5:59:24 AM UTC
This is great stuff but I have hit a road block that I can't figure out. I am trying to use this with a SQL 2008 db & using a data context that implements ObjectContext like so:

public class DataContext : ObjectContext

And then in my constructor I am passing a named connection string to the base like so:

public DataContext() : base("name=TestDB", "TestDB") {}

My connection string is in the web.config and loks like this:

<add name="TestDB" connectionString="Data Source=(local);Initial Catalog=Test.Database;Persist Security Info=True;User Id=Test;Password=test" providerName="System.Data.SqlClient" />

However when I try to run this I get the following exception:

"The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid."

Anybody have any thoughts?

Thanks, --Jim
Jim Oxenhandler
Friday, July 23, 2010 2:33:06 PM UTC
Scott,

Which namespace is the [RelatedTo] attribute in? There's one in System.ComponentModel.DataAnnotations but it doesn't have a RelatedProperty property, just ForeignKey and Property.
Monday, July 26, 2010 2:09:09 PM UTC
Very cool! Does code first development work with Oracle yet or is it only for MSSQL?
Monday, July 26, 2010 5:49:33 PM UTC
Code First actually calls the EF Provider it's currently working with to figure out correct storage types so it should work with Oracle providing you have an Oracle provider with full ADO.NET 4.0 support.

[)amien
Wednesday, July 28, 2010 4:04:44 PM UTC
How do you enable lazy loading using a DbContext?
Jim Oxenhandler
Friday, July 30, 2010 4:05:33 AM UTC
Is there a way to hook class-level validation into these objects? Let's say I wanted to look up the "First Published" date for a book and make sure that the Author was still alive then, or something like that where I've got to examine multiple fields on the object. I haven't seen an overridable method or anything like that -- any ideas?
Saturday, July 31, 2010 1:50:46 PM UTC
I have been doing something simlar with Subsonic in MVC 1.0 - code first is the future!

Its great to see that this is something that will become part of the core.

Gavin.
Wednesday, August 04, 2010 5:59:08 PM UTC
I am not sure which CTP4 version you are looking at but I am not able to find any RelatedTo attribute with named properties described in the ADO.NET blog or here. Moreover, the HasOptional or HasRequired does not work in the manner described here. For instance:

public class DefinedType {
public int Id{get;set;}
public virtual string Typename{get;set;}
public virtual ICollection<DefinedObject> DefinedObjects {get;set;}
}
public class DefinedObject {
public int Id{get;set;}
public virtual DefinedType DefinedType{get;set;}
}

Now with the configuration on DefinedObject with HasRequired(t => t.DefinedType).WithMany(o => o.DefinedObjects) the EF tries to query DefinedType_Typename on DefinedObject why??

Is this a bug or is there a version which we don't know about?

Thanks,
PG

PG
Friday, August 06, 2010 9:39:41 PM UTC
Is it possible to have a single Model bound to a dynamic table name? For Instance, in our database you can create multiple tables "Managers", "Employees", "Accountants" - all dynamic. Using Linq we overrode the MetaModel.GetTable to add custom attributes based on a parameter passed to the DataContext initializer. However, we are unable to do that with EF yet or we just don't see how it's possible. Any insight would be helpful (on the same vein we'd like to use the DataContext to create a new table when necessary)

-Morder
Morder
Thursday, August 12, 2010 10:11:41 AM UTC
Good post , thanks
monolight
Tuesday, August 24, 2010 3:50:23 PM UTC
Hi Scott,

I have some trouble with modifying a 1-1 relationship. I use a one direction relationship: Product -> Brand. When I modify the brand by selecting another existing one, the DbContext.SaveChanges() method creates a new Brand with the same values of the exsiting Brand but with a new Id. How do I solve this problem?

My model classes look like this:

[ModelBinder(typeof(ProductModelBinder))]
public class Product
{
[Key]
public int ProductId { get; set; }

public string ProductName { get; set; }

[ScaffoldColumn(false)]
public int BrandId { get; set; }

[DropDownList("Brands", "BrandId", "BrandName", "[Select brand]")] // See http://bit.ly/5Pv8eR
[RelatedTo(ForeignKey = "BrandId")]
public Brand Brand { get; set; }
}
}

public class Brand
{
[Key]
[RelatedTo(Property = "BrandId")]
public int BrandId { get; set; }

public string BrandName { get; set; }
}


I created a MVC2 View with EditorForModel() using the Product as model, which resulted in a textbox (ProductName property) and a DropDown listbox (Brand property). When I change the value of the dropdownlist, I use the ProductModelBinder.GetPropertyValue() method to retrieve the selected Brand from the BrandRepository using the Brand.BrandId value I received from the view. In the controller, I created the following Action:

[HttpPost]
public ActionResult Edit(int id, FormCollection productData)
{
Product entry = productRepository.GetByID(id);
try
{
if (ViewData.ModelState.IsValid)
{
// This works nice: Product.Brand is changed with the selected other Brand; Product.BrandId
// contains the old BrandId

UpdateModel(entry, productData.ToValueProvider());

// This works nice too, now Product.BrandId contains the BrandId of the selected Brand.
// The Attach() method of this repository executes DbSet<Product>.Attach() and
// DbContext.ObjectContext.ObjectStateManager.ChangeEntityState(product, EntityState.Modified)

productRepository.Attach(entry);

// SaveChanges() goes wrong: now Product.Brand contains a NEW Brand with the
// values of the selected one and with a new BrandId

productRepository.SaveChanges();

return RedirectToAction("Index");
}
ViewData["Brands"] = brandRepository.GetAll();
return View(entry);
}
catch (Exception ex) { return View(entry); }
}


Please help! What's going wrong?



Thursday, August 26, 2010 2:38:18 AM UTC
Scott,
would the Code First DbContext work as a WCF Data Service?
I tried it, but got he following error :

The server encountered an error processing the request. The exception message is 'On data context type 'CustomerService', there is a top IQueryable property 'Customer' whose element type is not an entity type. Make sure that the IQueryable property is of entity type or specify the IgnoreProperties attribute on the data context type to ignore this property.'. See server logs for more details.
John
Friday, September 17, 2010 3:06:52 AM UTC
>would the Code First DbContext work as a WCF Data Service?
>I tried it, but got he following error :

In CTP4, DbContext doesn't directly support exposing to DataService but here's a simple workaround:
http://romiller.com/2010/07/19/ef-ctp4-tips-tricks-wcf-data-service-on-dbcontext/
Sunday, October 24, 2010 2:50:00 AM UTC
Hi Guys,



Below is a link to Tutorial for using Entity Framework with SQL Ce 4.0 as there is no design time support for SQL CE in VS2010



http://getsrirams.blogspot.com/2010/10/adonet-entity-data-model-for-sqlserver.html


Identity column issue in EF 3.5 with SQL CE 3.5 is fixed for SQL CE 4.0 in EF 4.
Friday, November 05, 2010 2:34:40 PM UTC
Scott:

ScottGu also had a blog entry on Code-First and modifying the underlying database mappings. In both of these posts, you two show how you can: 1) map a "complex property" into columns within the entity database table and 2) in your post specifically, how to use inheritance. What I'm wondering, though, is is it possible to split a POCO class's attributes into multiple database tables?

For example, in the ASP.NET membership system, there is no way to associate a user's first and last name with the Member object without doing one of two things: 1) Using the standard ASP.NET Profile provider or 2) creating your own MembershipProvider. What I would like to do is have a "super POCO object" that includes all information about a user (particularly first and last name, office number/location...it's not really "profile data", it's a part of who a member is in my project) and have those attributes be stored in two or more tables. This prevents, for instance, having to access these "properties" of member via Member.Profile.FirstName, or Member.User.UserName. Conceptually, it's easier if I could just write Membe.FirstName or Member.UserName, etc.
Sunday, November 07, 2010 5:28:27 AM UTC
Scott,

Great stuff - but I found one issue that you may already be aware of...

According to the EF Data Annotations setting the Required Attribute on a navigation reference property (ie a 1 to many relationship instead of a 0..1 to many).

I tried this in my model like so:

[Required]
public virtual Person Person { get; set; }

but its generating the PersonID column as nullable and its not giving an exception when leaving this property null. However, I tried setting the HasRequired method in the model Builder and it DID work as expected.

modelBuilder.Entity<Inquiry>().HasRequired(b => b.Person);

So I'm guessing this might just be a feature that is not yet wired up in the beta. Or please feel free to let me know if I am just missing something.

Thanks again for the awesome work you guys are doing.
Friday, November 12, 2010 9:25:00 PM UTC
Kevin - That should be fixed in the next CTP5.
Tuesday, November 16, 2010 10:02:29 PM UTC
Thanks Scott. Could you blog about a simple example of a one-to-many property that is implemented with a dropdown list? This seems like it would be a common problem, but I can't find an example.
Eric
Tuesday, November 16, 2010 10:25:52 PM UTC
Just to be clearer about my last post. If you wanted to add a Category to your book class, but you didn't need/want your category class to have a property that was a list of books in that category.
Eric
Thursday, December 02, 2010 11:15:01 PM UTC
Following your examples, I keep getting the "unable to infer a primary key" error on any of the tables I try to access. I am using the [Key] attribute as you indicated, but it seems to have no effect. I also tried declaring the key in OnModelCreating in the DbContext as you suggested. This at least gives me a different error: "Key expression is not valid." Has anyone else run into this? I'm using .NET 4, VisualStudio 2010, etc.
Josh Fuller
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.