Thursday, February 16, 2012

ASP.NET Entity Framework 4.3 - What's my Id???

Whilst working on a simple data access layer using Sql Ce 4, POCO C# and using the Repository Pattern it occurred to me that when implementing a SaveChanges method that there was no real effective way to prevent a subsequent developer coming along and instantiating a new instasnce of some entity, directly setting the Id property and calling SaveChanges! I thought about nesting the entity within the repository and changing access levels on classes and properties but nothing really worked.

At this point I figured that there are much smarter people out there that have already solved this problem - I'll just have a look and see how they did it (A good view when standing on the shoulders of giants!).

I fired up visual studio, hit nuget for EF 4.3 updated everything, wrote a very contrived example waited for an exception at which point I'd delve into the code and possibly with a little reflection work out what was going on.

Sadly that's not what happened. I discovered that if you instantiate an instance of an entity manually populate its Id and call save changes it simply quietly adds it to the db with the next available identity and carries on!

Although this may well never actually happen in the real world I thought it was interesting none the less.

If I'm being a complete idiot here please do let me know!

- Class1.cs

namespace FactoryPatternSandbox.Core
{
    public class TestContext : DbContext
    {
        public TestContext()
            : base("name=conn")
        {
 
        }
 
        public DbSet<ExampleItem> ExampleItemSet {getset;}
        
    }
 
    public class ExampleItem
    {
        public int Id { getset; }
        public string Text { getset; }
    }
}

Default.aspx
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            using (Core.TestContext context = new Core.TestContext())
            {
                Core.ExampleItem example = new Core.ExampleItem();
                // Set Id to a random hard coded int
                example.Id = 1234;
                // Set arbitrary text value
                example.Text = DateTime.Now.ToString();
                // Add to context with Id 1234
                context.ExampleItemSet.Add(example);
                // output Id to Literal (Output = 1234)
                something.Text = example.Id.ToString();
                context.SaveChanges();
// At this point the Id *should* have been added to the DB as 1234
// or thrown an exception e.g. CannotAssignIdToNewEntityException()
// However checking the DB the item has been added with the next
// available Id as per a normal INSERT INTO with an IDENTITY column specification
// But its not actually told us (via an exception) that the Id value
// has indeed changed so when we call for our random hard coded int
// it throws an exception saying there are no items in the collection.
Core.ExampleItem exampleFromDb = context.ExampleItemSet.Where(l => l.Id == 1234).Single();
 
            }
        }
    }
Post a Comment