I am using the Entity Framework v 4.1 and for certain cases, when I insert data into the database using my DBContext/Code First approach, I need to be able to bypass the Identity creation of my primary key. The desired behavior is that we don't always want to do this. So, after a lot of experimentation and deciphering of other people's posts/questions/blogs, I think I figured it out.
Since I am not using the Model editor, I use the fluent APIs to explicitly set my mappings, fk's, relationships, etc... (Why am I using the APIs rather than the model editor is a different discussion). Anyways,
When configuring a mapping to a table that has an identity column, the first thing we need to tell the is that we will not abby by the default HasDatabaseGeneratedOption setting which is implicitly set to DatabaseGeneratedOption.Identity. We must set it to None. But that's not all, in addition, we must use the ExecuteStoreCommand to execute the raw SQL SET IDENTITY_INSERT command, e.g.:
DbModelBuilder
private
{
SetIdentityCommandText, tableName, enable ?
} const string SetIdentityCommandText = "SET IDENTITY_INSERT {0} {1}";private int ToggleIdentityInsertFor<T>(bool enable) var tableName = SourceTable.GetFullName<T>(); return DataContext.ObjectContext.ExecuteStoreCommand(string.Format("ON" : "OFF"));
There is still one more thing we need to worry about. One must be aware that SET IDENTITY_INSERT is a session-dependent command, what that means is that if another connection is established, the identity behavior will be the default for that new connection/session.
Having said that, since by its nature we now need to define a transaction scope so that we can do at least 3 things:
1. Disable the identity
2. Insert your entity to the table
3. Enable back the identity
(in my case I do more complex operations)
A transaction scope is required for all of this to work, otherwise your #2 operation will reset the DB connection and therefor your #1 item is lost.
And the last catch, you must explicitly open the connection right after you instantiate the transaction scope, otherwise all of this hard work will still be a waste. For that I created a wrapper to the Transaction Scope so that my client libraries are completely shielded from this:
using System;using System.Data;using
namespace X
{/// <summary>/// Wraps the System.Transactions API for TransactionScope/// </summary>public class TransactionCoordinator : IDisposable{
{
_dataContext = (
_scope =
_dataContext.ObjectContext.Connection.Open();
}
~TransactionCoordinator()
{
private XY _dataContext;private TransactionScope _scope;private bool disposed = false;public TransactionCoordinator(IDataContext dataContext)XY)dataContext;new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted });// Simply call Dispose(false).Dispose(
}
{
_scope.Complete();
{
_dataContext.ObjectContext.Connection.Close();
}
}
{
Dispose(
}
{
{
{
{
_scope.Dispose();
}
}
disposed =
}
}
}
}false);public void Complete()if (_dataContext.ObjectContext.Connection.State == ConnectionState.Open)public void Dispose()true);GC.SuppressFinalize(this);protected virtual void Dispose(bool disposing)if (!disposed)if (disposing)if (_scope != null)true;
Now I am happily overriding the identity. Now for the second part of my problem, I need to toggle this behavior ON and OFF at run-time. Time to delve deeper into the DBModelBuilder
I hope this saves you lots of time.
System.Transactions;
Another IT guy's blog
Friday, July 15, 2011
Thursday, March 17, 2011
Multiple types were found that match the controller named '[your controller name]'. This can happen if the route that services this request ('{controller}/{action}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
My scenario:
I was forced to rename an ASP.NET MVC application due to some problems with MSBuild (different story). For the sake of cleanliness I also renamed namespaces within my application.
Every time I ran the app I had the following exception:
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The WebRuntime solution which is the source code for the RTM version of ASP.NET MVC offered some clues as to why since it performs Assembly loading. The bin directory that resides under my WebApplication project still contained the old dll (prior to renaming). This confused MVC as it encountered multiple controllers named the same. Simply delete the old dll and the issue should dissapear.
Also make sure that any strongly-typed Views and Global.asax mark-up are updated with the correct namespaces.
I was forced to rename an ASP.NET MVC application due to some problems with MSBuild (different story). For the sake of cleanliness I also renamed namespaces within my application.
Every time I ran the app I had the following exception:
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The WebRuntime solution which is the source code for the RTM version of ASP.NET MVC offered some clues as to why since it performs Assembly loading. The bin directory that resides under my WebApplication project still contained the old dll (prior to renaming). This confused MVC as it encountered multiple controllers named the same. Simply delete the old dll and the issue should dissapear.
Also make sure that any strongly-typed Views and Global.asax mark-up are updated with the correct namespaces.
Subscribe to:
Posts (Atom)