Don't flush the session after an exception occurs - NHibernate - asp.net-mvc

I am developing a ASP.NET MVC web app under .NET 3.5, NHibernate and hosted on Windows Azure. When, the webapp is run from the local development fabric it works fine. Yet, when I move it to Windows Azure, every insert performed from the MVC web role ends up with the exception listed below.
Any idea what's wrong with my NHibernate logic? (might be the session management, not sure)
[AssertionFailure: null id in Lokad.Translate.Entities.User entry (don't flush the Session after an exception occurs)]
NHibernate.Event.Default.DefaultFlushEntityEventListener.CheckId(Object obj, IEntityPersister persister, Object id, EntityMode entityMode) +292
NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues(Object entity, EntityEntry entry, EntityMode entityMode, Boolean mightBeDirty, ISessionImplementor session) +93
NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) +158
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) +469
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) +339
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) +85
NHibernate.Impl.SessionImpl.Flush() +275
NHibernate.Transaction.AdoTransaction.Commit() +236
Lokad.Translate.Repositories.PageRepository.Create(Page page)
Lokad.Translate.Controllers.PagesController.Create(Page page)
lambda_method(ExecutionScope , ControllerBase , Object[] ) +69
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +251
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +31
System.Web.Mvc.<>c__DisplayClassa.b__7() +88
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +534
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +312
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +856
System.Web.Mvc.Controller.ExecuteCore() +185
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +221
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +586
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +177
Note that I am using _session.FlushMode = FlushMode.Commit; and that the User is used in a custom RoleProvider
public class SimpleRoleProvider : RoleProvider
{
readonly UserRepository Users = new UserRepository();
public override string[] GetRolesForUser(string username)
{
try
{
var user = Users.Get(username);
// no role if user is not registered
if (null == user) return new string[0];
// default role for registered user
return user.IsManager ? new[] { "Manager", "User" } : new[] { "User" };
}
catch (Exception)
{
// role should not fail in case of DB issue.
return new string[0];
}
}
}

You should never catch exceptions and ignore them during a NHibernate transaction.
I try to explain why.
There could be exceptions for instance caused by constraints in the database. (it could also be caused by mapping problems, exceptions thrown by properties or anything else.) NHibernate tries to synchronize the state in memory with the database. This is done on commit - and sometimes before queries to make sure that queries are done on actual data. When this synchronization fails, the state in the database is something random, some changes are persisted, others are not. The only thing you can do in such a case is closing the session.
Consider that decisions and calculations in your code are based on values in memory. But - in case of an ignored exception, this values are not the values in the database, they will never be there. So your logic will decide and calculate on 'fantasy-data'.
By the way, it is never a good idea to catch any exception (untyped) and ignore them. You should always know the exceptions you handle, and be sure that you can continue.
What you're doing here is swallowing programming errors. Believe me, the system will not be more stable. The question is only: do you notice the error when it occurs, or do you ignore it there and even persist the result of the error to the database? When you do the latter, you don't have to be surprised when your database is inconsistent and other error arise when you try to get the data from the database. And you will never ever find the code that is the actual cause of the error.

I have finally found a solution to my own problem. In case people would be interested, I am posting the solution here.
public class SimpleRoleProvider : RoleProvider
{
// isolated session management for the RoleProvider to avoid
// issues with automated management of session lifecycle.
public override string[] GetRolesForUser(string username)
{
using (var session = GlobalSetup.SessionFactory.OpenSession())
{
var users = new UserRepository(session);
var user = users.Get(username);
// no role if user is not registered
if (null == user) return new string[0];
// default role for registered user
return user.IsManager ? new[] {"Manager", "User"} : new[] {"User"};
}
}
}
Basically what was happening is that the RoleProvider repository does not seem to have the same lifecycle than regular in-view / in-controller repositories. As a result, at the time the RoleProvider is called, the NHibernate session has already been disposed causing the exception observed here above.
I have replaced the code by the following one here above. This one has its own NHibernate session management, and ends up working fine.

This exception can occur if your column names include reserved words (e.g. use status as a column name and it will become impossible to Save)

Related

Implementing MVC 5 IAuthenticationFilter

I don't understand the purpose/difference of OnAuthentication and OnAuthenticationChallenge aside from OnAuthentication running before an action executes and OnAuthenticationChallenge runs after an action executes but before the action result is processed.
It seems as though either one of them (OnAuthentication or OnAuthenticationChallenge) can do all that is needed for authentication. Why the need for 2 methods?
My understanding is OnAuthentication is where we put the logic of authenticating (or should this logic be in actual action method?), connecting to data store and checking for the user account. OnAuthenticationChallenge is where we redirect to login page if not authenticated. Is this correct? Why can't I just redirect on OnAuthentication and not implement OnAuthenticationChallenge. I know there is something I am missing; could someone explain it to me?
Also what is the best practice to store an authenticated user so that succeeding requests wouldn't have to connect to db to check again for user?
Please bear in mind that I am new to ASP.NET MVC.
Those methods are really intended for different purposes:
IAuthenticationFilter.OnAuthentication should be used for setting the principal, the principal being the object identifying the user.
You can also set a result in this method like an HttpUnauthorisedResult (which would save you from executing an additional authorization filter). While this is possible, I like the separation of concerns between the different filters.
IAuthenticationFilter.OnAuthenticationChallenge is used to add a "challenge" to the result before it is returned to the user.
This is always executed right before the result is returned to the user, which means it might be executed at different points of the pipeline on different requests. See the explanation of ControllerActionInvoker.InvokeAction below.
Using this method for "authorization" purposes (like checking if a user is logged in or in a certain role) might be a bad idea since it might get executed AFTER the controller action code, so you might have changed something in the db before this gets executed!
The idea is that this method can be used to contribute to the result, rather than perform critical authorization checks. For example you could use it to convert an HttpUnauthorisedResult into a redirect to different login pages based on some logic. Or you could hold some user changes, redirect him to another page where you can request additional confirmation/information and depending on the answer finally commit or discard those changes.
IAuthorizationFilter.OnAuthorization should still be used to perform authentication checks, like checking if the user is logged in or belongs to a certain role.
You can get a better idea if you check the source code for ControllerActionInvoker.InvokeAction. The following will happen when executing an action:
IAuthenticationFilter.OnAuthentication is called for every authentication filter. If the principal is updated in the AuthenticationContext, then both context.HttpContext.User and Thread.CurrentPrincipal are updated.
If any authentication filter set a result, for example setting a 404 result, then OnAuthenticationChallenge is called for every authentication filter, which would allow changing the result before being returned. (You could for example convert it into a redirect to login). After the challenges, the result is returned without proceeding to step 3.
If none of the authentication filters set a result, then for every IAuthorizationFilter its OnAuthorization method is executed.
As in step 2, if any authorization filter set a result, for example setting a 404 result, then OnAuthenticationChallenge is called for every authentication filter. After the challenges, the result is returned without proceeding to step 3.
If none of the authorization filters set a result, then it will proceed to executing the action (Taking into account request validation and any action filter)
After action is executed and before the result is returned, OnAuthenticationChallenge is called for every authentication filter
I have copied the current code of ControllerActionInvoker.InvokeAction here as a reference, but you can use the link above to see the latest version:
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
Contract.Assert(controllerContext.RouteData != null);
if (String.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
if (actionDescriptor != null)
{
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
try
{
AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor);
if (authenticationContext.Result != null)
{
// An authentication filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authenticationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result);
}
else
{
AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
if (authorizationContext.Result != null)
{
// An authorization filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authorizationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ValidateRequest(controllerContext);
}
IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
// The action succeeded. Let all authentication filters contribute to an action result (to
// combine authentication challenges; some authentication filters need to do negotiation
// even on a successful result). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
postActionContext.Result);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
challengeContext.Result ?? postActionContext.Result);
}
}
}
catch (ThreadAbortException)
{
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
throw;
}
catch (Exception ex)
{
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled)
{
throw;
}
InvokeActionResult(controllerContext, exceptionContext.Result);
}
return true;
}
// notify controller that no method matched
return false;
}
As for not hitting the db on every request when setting the principal, you could use some sort of server side caching.

Breeze expand error

Not sure if this is possible using Breeze, but we have a situation where we need to return an IQueryable from 2 different sources.
Our business logic called from our controller action checks to see if some data is stored within a database, if so an IQueryable is returned from the repository which uses the EFContextProvider.
Otherwise, a List<T> is created containing default data and turned into an IQueryable, which is then returned.
On the client side, our query contains .expand to ensure the navigation properties are populated with the required data.
This works fine when the IQueryable is coming from the EF, but crashes with the following error when creating the List<T>:
{"$id":"1","$type":"System.Web.Http.HttpError, System.Web.Http","Message":"An error has occurred.","ExceptionMessage":"'System.Linq.EnumerableQuery<MyObject>' does not contain a definition for 'Include'","ExceptionType":"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException","StackTrace":" at CallSite.Target(Closure , CallSite , Object , String )\r\n at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)\r\n at Breeze.WebApi.QueryHelper.<>c__DisplayClass14.<ApplyExpand>b__11(String expand)\r\n at System.Collections.Generic.List`1.ForEach(Action`1 action)\r\n at Breeze.WebApi.QueryHelper.ApplyExpand(IQueryable queryable, String expandsQueryString)\r\n at Breeze.WebApi.QueryHelper.ApplySelectAndExpand(IQueryable queryable, NameValueCollection map)\r\n at Breeze.WebApi.BreezeQueryableAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)\r\n at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception)\r\n at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response)\r\n at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t)\r\n at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)"}
Is this an issue with Breeze (we're using 1.4.2 at present), or is it something I'm doing wrong?
I think your best bet in this case in this case is remove the 'expand' from the client and move it the server (as an Include). Something like this:
[HttpGet]
public IQueryable<Customer> Customers(someCriteria) {
if (... haveData ...) {
return ContextProvider.Context.Customers.Include("Orders");
} else {
return DefaultCustomerList.AsQueryable()
}
}

How to handle exception in Flush phase?

how can I handle exception that is thrown in NHibernate method Flush? I have a action for deleting objects. It loads the objects from repository using posted ids and calls repository.Delete(obj).
Leaving aside that my mapping in NHibernate is not complete and the delete results in "The DELETE statement conflicted with REFERENCE constraint" exception, this is good case to implement the exception hadling for this case.
So the exception is thrown in Flush and the Flush is called in UnitOfWorkPerRequestTask, which is task created and destroyed on every request and it starts and flushes the UnitOfWork (Rhino.Commons.UnitOfWork). This task is registered using Windsor container and LifestyleType.Transient and it is called by HttpApplication inside Begin and EndRequest methods.
Is there any way how to handle this exception in my delete action, so I can notice user that this object cannot be deleted because of some relationships?
The exception stack trace is here (not full):
NHibernate.Transaction.AdoTransaction.Commit() +212
Rhino.Commons.NHibernateTransactionAdapter.Commit() +33
Rhino.Commons.BaseUnitOfWorkFactory.TransactionalFlush(IsolationLevel isolationLevel) +116
Rhino.Commons.BaseUnitOfWorkFactory.TransactionalFlush() +35
Cereal.Mvc.DataModule.Tasks.UnitOfWorkPerRequestTask.DisposeCore() in C:\projects\Sample\Cereal.Mvc.DataModule\Tasks\UnitOfWorkPerRequestTask.cs:33
System.Web.Mvc.Extensibility.Disposable.Dispose(Boolean disposing) in C:\projects\System.Web.Mvc.Extensibility\Abstraction\Disposable.cs:52
System.Web.Mvc.Extensibility.Disposable.Dispose() in C:\projects\System.Web.Mvc.Extensibility\Abstraction\Disposable.cs:35
Castle.MicroKernel.LifecycleConcerns.DisposalConcern.Apply(ComponentModel model, Object component) +47
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.ApplyConcerns(Object[] steps, Object instance) +129
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.ApplyDecommissionConcerns(Object instance) +106
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalDestroy(Object instance) +37
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Destroy(Object instance) +37
Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Release(Object instance) +48
Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleManager.Evict(Object instance) +38
Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule.Application_EndRequest(Object sender, EventArgs e) +305
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
Thanks for help.
If you call Flush() in a UnitOfWork, you can only catch the error and log it.
If you want your users inform about the error, then close the transaction or do the Flush earlierer (as stated in the comments of Paco and cbp). One place is to handle it in your action method. Check the outcome and report it to the user with an error page.

System.Data.SqlClient.SqlException: Invalid object name 'dbo.Projects' [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
My MVC app is returning SqlExceptions when trying to access any table in my database.
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.Projects'.
My app us linq for the data layer.
If I use an old dll it works fine, (so doesn't seem to be a problem with the DB) just this latest app dll that I've uploaded.
details
[SqlException (0x80131904): Invalid object name 'dbo.Projects'.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection) +1950890
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection) +4846875
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj) +194 System.Data.SqlClient.TdsParser.Run(RunBehavior
runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj) +2392
System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +83
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,
RunBehavior runBehavior, String resetOptionsString) +297
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean
async) +954
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
behavior, String method) +141
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior
behavior) +12 System.Data.Common.DbCommand.ExecuteReader() +12
System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query,
QueryInfo queryInfo, IObjectReaderFactory factory, Object[]
parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object
lastResult) +975
System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query,
QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[]
userArguments, ICompiledSubQuery[] subQueries) +113
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression
query) +344
System.Data.Linq.DataQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
+35 System.Linq.Buffer1..ctor(IEnumerable1 source) +247 System.Linq.<GetEnumerator>d__0.MoveNext() +108
System.Linq.Buffer1..ctor(IEnumerable1 source) +259
System.Linq.<GetEnumerator>d__0.MoveNext() +108
System.Collections.Generic.List1..ctor(IEnumerable1 collection)
+7665172 System.Linq.Enumerable.ToList(IEnumerable1 source) +61 Mezza_crm.Controllers.ProjectsController.GetProjectList(NameValueCollection form) in C:\mezza_crm\mezza_crm\Controllers\ProjectsController.cs:164
Mezza_crm.Controllers.ProjectsController.List() in
C:\mezza_crm\mezza_crm\Controllers\ProjectsController.cs:53
lambda_method(ExecutionScope , ControllerBase , Object[] ) +39
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase
controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext
controllerContext, IDictionary2 parameters) +178
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext, ActionDescriptor actionDescriptor, IDictionary2
parameters) +24
System.Web.Mvc.<>c__DisplayClassa.b__7()
+52 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter
filter, ActionExecutingContext preContext, Func1 continuation) +254
System.Web.Mvc.<>c__DisplayClassc.<InvokeActionMethodWithFilters>b__9()
+19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext
controllerContext, IList1 filters, ActionDescriptor actionDescriptor,
IDictionary`2 parameters) +192
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext
controllerContext, String actionName) +399
System.Web.Mvc.Controller.ExecuteCore() +126
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
+27 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext
requestContext) +7
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
+151 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +57
System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext
httpContext) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+181 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
Check the Initial Catalog parameter in your connection string. It may be that your code is looking in the wrong database for the Projects object.
For example, if you have database syncing setup in such a way that only a subset of the master-database's tables are transferred, you can encounter this error if Linq to SQL is expecting all tables to be in the database pointed to by the connection string.
I have seen that the new versions when you define the resulting entities better define them in the following way if you handle a different scheme, I had a similar problem
You must add System.ComponentModel.DataAnnotations.Schema
using System.ComponentModel.DataAnnotations.Schema;
[Table("InstitucionesMilitares", Schema = "configuracion")]
Do you have access to the SQL Server you are querying?
Can you see a Table or View called dbo.Projects there?
If not, that would be a good place to look.
Linq to SQL creates an object map between the database and the application. If your new DLL that you're deploying doesn't match with the database anymore, then this is the sort of error you'd expect to get.
Do you perhaps have different database schemas between your development environment and the deployment environment?
This maybe due to an incorrect table name from where you are fetching the data. Please verify the name of the table you mentioned in asmx file and the table created in database.
Delete _MigrationHistory table in (yourdatabseName > Tables > System Tables) if you already have in your database and then run below command in package manager console
PM> update-database
TLDR: Check that you don't connect to the same table/view twice.
FooConfiguration.cs
builder.ToTable("Profiles", "dbo");
...
BarConfiguration.cs
builder.ToTable("profiles", "dbo");
For me the issue was that I was trying to add an entity that connected to the same table as some other entity that already existed.
I added a new DbSet with entity and config, thinking we don't have it in our solution yet, however after searching for table name through all solution I found another place where we already connected to it.
Switching to use existing DbSet and removing my newly added one solved the issue.
The cause of this problem could be a property setting of the database (Sql2008R2 with .NET4).
Problem is reproducible at will when changing the COLLATION value of a database.
To display COLLLATION, use the Sql Server Mgmt Studio.
Right-click the database and select Properties -> General, Then look under Maintenance for the COLLATION value
To change COLLATION, (still) use the Sql Server Mgmt Studio.
Right-click the database and select Properties -> Options, From there, you can change the COLLATION value
If you are in that phase of development where you have an method inside your context class that creates testdata for you, don't call it in your constructor, it will try to create those test records while you don't have tables yet. Just sharing my mistake...
Try to do this way
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
or if you use .net core try it
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Usuario>().ToTable("Usuario");
}
Replace Usuario for your Entity Name, like a DbSet<<EntityName>> Entities without Plural
If you use two databases you can add another DataClasses.dbml and map the second database into it.
It works.
I had the same error. The cause was that I had created a table with wrong schema(it ought to be [dbo]). I did the following steps:
I dropped all tables which does not have a prefix "dbo."
I created and run this query:
CREATE TABLE dbo.Cars(IDCar int PRIMARY KEY NOT NULL,Name varchar(25) NOT NULL,
CarDescription text NULL)
GO
The problem I had was because I had made a database in my LocalDb.
If that's the case then you have to write is as shown below:
"SELECT * FROM <DatabaseName>.[dbo].[Projects]"
Replace with your database name.
You can probably also drop the "[ ]"
I have tried almost all the answers from below list, but did not work for me. But read the exception well and then tried rename my Dbset name TransactionsModel to Transactions
and it work for me.
old Code:
public class MyContext : DbContext
{
//....
public DbSet<Models.TransactionsModel> TransactionsModel { get; set; }
}
New Code:
public class MyContext : DbContext
{
//....
public DbSet<Models.TransactionsModel> Transactions { get; set; }
}

ASP.NET-MVC (IIS6) Error on high traffic: Specified cast is not valid

I just launched my tiny webapp on my humble dedicated server (Win2003)... running ASP.NET MVC, LINQ2SQL, SQL Express 2005, and IIS6 (setup with wildcard mapping)
The website runs smoothly 90% of the times. However, on relatively high traffic, LINQ2SQL throws the error:
Specified cast is not valid
This error is ONLY thrown at high traffic. I have NO IDEA how or exactly why this happens. Caching did not remove this problem entirely.
Anyone seen this problem before? are there any secret SQL Server tweaking I should've done?
Or at least, any ideas on how to diagnose this issue? because i'm out!
Naimi
Stacktrace (from Event Log):
at System.Data.SqlClient.SqlBuffer.get_SqlGuid()
at System.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)
at Read_Friend(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at Dudlers.Web.Models.DudlersDataContext.GetFriendRequests(Guid userId) in C:\Web\Models\DudlersDataContext.cs:line 562
at Dudlers.Web.Controllers.BaseController.View(String viewName, String masterName, Object viewData) in C:\Web\Controllers\BaseController.cs:line 39
at System.Web.Mvc.Controller.View(String viewName)
at Dudlers.Web.Controllers.CatController.Index() in C:\Web\Controllers\CatController.cs:line 25
at lambda_method(ExecutionScope , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(MethodInfo methodInfo, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.c__DisplayClassb.b__8()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.c__DisplayClassb.c__DisplayClassd.b__a()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(MethodInfo methodInfo, IDictionary`2 parameters, IList`1 filters)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext)
at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
We had a similar problem with LINQ that we get "Unable to cast object of type 'System.Int32' to type 'System.String'" and "Specified cast is not valid."
Examples of stacktraces
System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.
at System.Data.SqlClient.SqlBuffer.get_String()
at System.Data.SqlClient.SqlDataReader.GetString(Int32 i)
at Read_Person(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at RF.Ias.Services.Person.BusinessLogic.PersonTransactionScripts.GetPersons(IEnumerable`1 personIds, Boolean includeAddress, Boolean includeContact)
at CompositionAopProxy_5b0727341ad64f29b816c1b73d11dd44.GetPersons(IEnumerable`1 personIds, Boolean includeAddress, Boolean includeContact)
at RF.Ias.Services.Person.ServiceImplementation.PersonService.GetPersons(GetPersonRequest request)
System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_Int32()
at System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)
at Read_GetRolesForOrganisationResult(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at RF.Ias.Services.Role.DataAccess.RoleDataAccess.GetRolesForOrganisation(GetRolesForOrganisationCriteria criteria, Int32 pageIndex, Int32 pageSize, Int32& recordCount)
at RF.Ias.Services.Role.BusinessLogic.RoleTransactionScripts.GetRolesForOrganisation(GetRolesForOrganisationCriteria criteria, Int32 pageIndex, Int32 pageSize, Int32& recordCount)
at CompositionAopProxy_4bd29c6074f54d10a2c09bd4ab27ca66.GetRolesForOrganisation(GetRolesForOrganisationCriteria criteria, Int32 pageIndex, Int32 pageSize, Int32& recordCount)
at RF.Ias.Services.Role.ServiceImplementation.RoleService.GetRolesForOrganisation(GetRolesForOrganisationRequest request)
We used to get these exceptions if we first got a exception like this "System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first." or " A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)".
The first exception occur for a different instance of the DataCOntext then for all those that then are following.
After some research and asking in this thread , I found that the reason was that I did not dispose the DataContexts. After I started to do that, it dissappered.
Sounds like maybe a race condition, or perhaps a rare bug that is only correlated with high traffic because that when most of your requests occur.

Resources