Concurrent access to a database with Entity Framework == EntityException - sql

I've a MS SQL 2008 database which is accessed through LINQ for data update/retrival.
My linq is accessed by WCF services in a PerCall instantiation mode for an heavy application. This application has several thread which makes calls to the service, and several application are running in the sametime.
I've often some EntityException happening:
System.Data.EntityException was caught
Message=An error occurred while starting a transaction on the provider connection. See the inner exception for details.
Source=System.Data.Entity
StackTrace:
at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.EntityClient.EntityConnection.BeginTransaction()
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges() in D:\Workspace\XYZWASDF\DataServer\DataServer.cs:line 123
InnerException: System.Data.SqlClient.SqlException
Message=Une nouvelle transaction n'est pas autorisée parce que d'autres threads sont en cours d'exécution dans la session.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=1
Number=3988
Procedure=""
Server=ift-srv114
State=1
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName)
at System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso)
at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel)
at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
InnerException:
(Sorry it's not very readable). (The message of the internal exception mean "A new transaction is not allowed because there are other threads running in the session."
I've check, I'm not in a loop, it's purely random when it makes this exception, and I've no idea about how to avoid this.
any help will be really appreciated :)
Thank you!
EDIT: Here is an example of where I got this exception SOMETIMES
//My DataServer method, which is a singleton
[MethodImpl(MethodImplOptions.Synchronized)]
public void SaveChanges()
{
lock (_lockObject)
{
try
{
_context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
_changeListener.ManageIDAfterInsert();
}
catch (Exception ex)
{
Logger.Instance.Error("[DataServer:SaveChanges] Got an error when trying to save an object", ex);
//HERE I've this error
}
}
}
//One example where I can have exception sometimes, this is called through a WCF service, so I have a method which attach the object and then save it
private OrderStatus AddOrderStatus(OrderStatus orderStatus)
{
DataServer.DataServer.Instance.InsertOrUpdateDetachedObject(orderStatus);
return orderStatus;
}

Without seeing your code, the short answer is that EntityFramework is not thread-safe. You're getting this error in a seemingly random pattern when two+ threads overlap when trying to try access your ObjectContext. I assume you've stuffed your context into a static variable. Either make the context a local variable or write locking around access to the ObjectContext.
If you want a more specific answer posting your code will help.
Edit
Your issue is that two threads are trying to use the context at the same time, or 1 thread is leaving a transaction open then and a second thread comes through trying to use your singleton context. Your code snippet raises more questions for me than I had before.
In your code example is _lockObject a static variable?
Why do you show the lock in SaveChanges but then explain an error is being thrown
from InsertOrUpdateDetachedObject? Can we see the code for InsertOrUpdateDetachedObject?
Does SaveChanges use the same _lockObject as all other methods that access the context directly?
Is your call to _context.SaveChanges the only way you save to the DB or do you have other areas that open transaction contexts on their own?
Your using a singleton so your context is shared across multiple calls. It might be preferable to instantiate a new new context for every WFC call.

Related

Connecting to SQL 2014 via PowerShell

This has me stumped.
.NET version 4.7
Powershell 5.1
I am trying to use the : new-object System.Data.SqlClient.SqlConnection statement
to connect to a MS-SQL server.
The code connects when run as Administrator but fails when run as another user that is a member of Local Administrators group.
The user has (I think) all required SQL permissions and no SQL hardening has been done. It is sysadmin on the server both with a Windows account and a SQL account.
Using
try { new-object System.Data.SqlClient.SqlConnection }
catch { write-host $_.Exception.ToString() }
to simply catch the exception.
It returns Requested registry access is not allowed
Using ProcMon there is absolutely no difference in the registry calls what so ever between the two users except that under administrator 3 threads exit and under the user only 1.
I am not convinced it is an actual registry permission as I gave the account explicit permissions on both HKLM and HKCU in the lab.
If anyone has seen this and/or can recommend a fix please hit me up.
(The script has to run as the user account because it is called from within SQL and therefore invoked under the service account context of the SQL Server Agent)
Here is the exception:
try { new-object System.Data.SqlClient.SqlConnection }
catch { write-host $_.Exception.ToString() }
System.Management.Automation.MethodInvocationException: Exception calling ".ctor" with "0" argument(s): "The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception." ---> System
.TypeInitializationException: The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Data.SqlClien
t.SqlConnectionFactory' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.Data.SqlClient.SqlPerformanceCounters' threw an exception. ---> System.Security.Se
curityException: **Requested registry access is not allowed.**
at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource)
at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
at System.Diagnostics.PerformanceCounterLib.FindCustomCategory(String category, PerformanceCounterCategoryType& categoryType)
at System.Diagnostics.PerformanceCounterLib.IsCustomCategory(String machine, String category)
at System.Diagnostics.PerformanceCounter.InitializeImpl()
at System.Diagnostics.PerformanceCounter.set_RawValue(Int64 value)
at System.Data.ProviderBase.DbConnectionPoolCounters.Counter..ctor(String categoryName, String instanceName, String counterName, PerformanceCounterType counterType)
at System.Data.ProviderBase.DbConnectionPoolCounters..ctor(String categoryName, String categoryHelp)
at System.Data.SqlClient.SqlPerformanceCounters..ctor()
at System.Data.SqlClient.SqlPerformanceCounters..cctor()
--- End of inner exception stack trace ---
at System.Data.SqlClient.SqlConnectionFactory..cctor()
--- End of inner exception stack trace ---
at System.Data.SqlClient.SqlConnection..cctor()
--- End of inner exception stack trace ---
at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType)
at System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType serverType)
at System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType serverType, Object[] props, Boolean bNewObj)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
--- End of inner exception stack trace ---
at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)
PS SQLSERVER:>

an error in ASP .NET4 + Linq

I'm working on a project that using ASP .NET 4 C# (with Linq) and SQL server. All run well open page on my own computer IIS and connect to local sql database. and it is ok if connection to server database with IIS from my computer. Error happen if open published page (of cause it run from server IIS and will connect to server database).
Error from server's event log is
Log Name: Application
Source: ASP.NET 4.0.30319.0
Date: 4/17/2015 1:33:11 PM
Event ID: 1309
Task Category: Web Event
Level: Warning
Keywords: Classic
User: N/A
Computer: SZHDB1.ds.jdsu.net
Description:
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 4/17/2015 1:33:11 PM
Event time (UTC): 4/17/2015 5:33:11 AM
Event ID: 89f5a478bff241d3aaa4798ce86ad707
Event sequence: 22
Event occurrence: 1
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/1/ROOT/IMS-2-130737223782305527
Trust level: Full
Application Virtual Path: /IMS
Application Path: D:\WebSite\IMS\
Machine name: SZHDB1
Process information:
Process ID: 3944
Process name: w3wp.exe
Account name: IIS APPPOOL\ASP.NET v4.0
Exception information:
Exception type: UpdateException
Exception message: An error occurred while updating the entries. See the inner exception for details.
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at Log.set_storeLog(String value) in C:\Users\che57576\Documents\Visual Studio 2010\Projects\InstrManage\InstrManage\App\Common.cs:line 26
at InstrManage.Admin.Group.GridView_group_SelectedIndexChanged(Object sender, EventArgs e) in C:\Users\che57576\Documents\Visual Studio 2010\Projects\InstrManage\InstrManage\Admin\Group.aspx.cs:line 164
at System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
String or binary data would be truncated.
The statement has been terminated.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary2 identifierValues, List1 generatedValues)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
and the related code are here:
'Common.cs':
public class Log
{
string conn, username;
public string storeLog
{
set
{
using (AdminEntities myEntrities = new AdminEntities(conn))
{
IMSlog log = new IMSlog();
log.user_name = username;
log.date_time = DateTimeOffset.Now;
log.what = value;
myEntrities.IMSlogs.AddObject(log);
myEntrities.SaveChanges(); //this is line 26
}
}
}
public Log(string linqConn,string userName)
{
conn = linqConn;
username = userName;
}
}
'Group.aspx.cs':
protected void Page_Load(object sender, EventArgs e)
{
log = new Log(sqlconnstr, Session["UserName"].ToString());
}
and in the same page, in the event:
protected void GridView_group_SelectedIndexChanged(object sender, EventArgs e)
{
bool result;
result = Int32.TryParse(GridView_group.SelectedRow.Cells[0].Text.ToString(), out index);
currentStatus = (GridView_group.SelectedRow.FindControl("CheckBox1") as CheckBox).Checked;
using (TransactionScope scope = new TransactionScope())
{
using (AdminEntities myEntrities = new AdminEntities(sqlconnstr))
{
admin_group c = (from r in myEntrities.admin_group
where r.group_id == index
select r).First();
c.group_enable = !currentStatus;
myEntrities.SaveChanges();
log.storeLog = "Set group ID " + index.ToString() + " to " + Convert.ToString(!currentStatus); // this is line 164
}
scope.Complete(); // To commit.
}
queryGroup();
}
when the above event be trigger, the error will happen.
I've search from lots of time, not sure why my laptop is ok but server cannot.
my laptop is win7 and sql express.
server is asp .net 4 and SQL server 2008.
The problem seems to be that you are trying to save a value too long for the length available in the database.
To find the problem, try to look at the length of the username you are trying to save and compare it to what's available in the database.
By setting a breakpoint on row #26 in Common.cs, you should be able to see the content of the variable username.
Once you find the problem, you can increase the size in your database. Also, it's recommended to validate the length of your username directly in your Web Application so the user can't enter a username too long for your database, an error message should be sent to the user asking him to use a shorter username.
One of the following assignments is too large for your data store
log.user_name = username;
log.date_time = DateTimeOffset.Now;
log.what = value;
You can also check if log.date_time is assigned the correct value

Nhibernate queries fail itermitently

I'm having a really hard time nailing down a problem coming from NHibernate (3.3). The application serves some 150 req/s in a six node NLB cluster. The application behaves ok generally, but sometimes maybe 1-2 day the following error comes in the logs and all queries fail.
I'm using adonet.batch_size of 15 and MultipleActiveResultSets=True is set to true. All controllers inherit from AsyncController (this is an ASP.NET MVC 4 app), so session state is read only to maximize concurrency.
Initially, we had a lot of trouble NHibernate Session handling because the AbstractBatcher did a pretty poor job managing which readers were related to which connection. So, in a high load, readers would try to read from connections that were already closed. We solved this by defining manually the lifetime of a SQLConnection which stabilized things.
However, the following comes up often. I think it is a symptom of something really wrong with the session factory. At this point, I'm thinking about reinitializing the session factory when an unhandled exception of this type is thrown, but that's not nice. Does anyone have any insight to why this happens?
System.NotSupportedException: PartialEvaluationExceptionExpression
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root)
at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
For those who may be facing this issue, I thought I'd give some insight of two years in production (thousands of users) of a fix that we put in place to address this issue.
In the base constructor we have something like this:
public MvcBaseController()
{
try
{
var currentRepositorySession = RepositorySession.Current;
dbConnection = new SqlConnection(currentRepositorySession.GetConnectionString());
dbConnection.Open();
session = currentRepositorySession.Create(false, dbConnection);
}
catch (Exception e)
{
LogDebug("Error was thrown: " + e.Message);
}
}
Binding the db connection to the NHibernate session forcefully is the only way to ensure that the AbstractBatcher doesn't close the session before all readers are done. On Dispose we have the following:
protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
if (session != null)
{
session.Dispose();
session = null;
}
}
catch (Exception ex)
{
LogDebug("Error was thrown: " + ex.Message);
}
try
{
if (dbConnection != null)
{
dbConnection.Close();
dbConnection.Dispose();
dbConnection = null;
}
}
catch (Exception ex)
{
LogDebug("Error was thrown: " + ex.Message);
}
}
base.Dispose(disposing);
}
This means that a connection is opened for every requests, which is fine. We had to increase SQL Server workers, but the system has been stable for two years now. The only time we've seen NHibernate session factory break is when there is a lot of data paged from the database, say 1 million records. Then the application pool overflows, and is orphaned. These were mostly code bugs and not related to the concurrency issues described in the question.

The wait operation timed out Win32Exception (0x80004005): The wait operation timed out azure

Following error comes when retrieving large amount of data from sql azure. I have already implement the Transient Fault Handling but still getting this error
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ComponentModel.Win32Exception: The wait operation timed out
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[Win32Exception (0x80004005): The wait operation timed out]
[SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) +1789270
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) +5340622
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +244
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +1691
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +275
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) +1421
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +177
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) +208
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +163
System.Web.SessionState.SqlSessionStateStore.SqlExecuteNonQueryWithRetry(SqlCommand cmd, Boolean ignoreInsertPKException, String id) +98
[HttpException (0x80004005): Unable to connect to SQL Server session database.]
System.Web.SessionState.SqlSessionStateStore.ThrowSqlConnectionException(SqlConnection conn, Exception e) +235
System.Web.SessionState.SqlSessionStateStore.SqlExecuteNonQueryWithRetry(SqlCommand cmd, Boolean ignoreInsertPKException, String id) +390
System.Web.SessionState.SqlSessionStateStore.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) +589
System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +565
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34009
http://i.stack.imgur.com/8BloW.png
The SqlClient.SqlCommand object has a property CommandTimeout. It's default value is 30 (seconds). You should set it to a higher value.
You can set the timeout value higher or you can turn off the timeout value, as I did in the below code. Note that you may encounter errors if the object that holds the data exceeds 2Gb. You may want to consider redesigning your query to take smaller chunks of data at a time.
// I'm populating an ADO.Net DataTable for this demo but populate whatever object you'd like
DataTable DtFromSQL = new DataTable();
SqlConnection myConnection = new SqlConnection("ConnectionString");
myConnection.Open();
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("enter some SQL query here", myConnection);
// A CommandTimeout Value of 0 turns the timout off, otherwise you can set it to some value in seconds
myCommand.CommandTimeout = 0;
myReader = myCommand.ExecuteReader();
DtFromSQL.Load(myReader8);
myConnection.Close();
DtFromSQL;

WCF with Entity Framework Error Part II

Newbie, please bear with me as I just started yesterday with WCF.
I am using Northwind for the data and only added Customers, Orders, Order Details and Products to the model, so nothing fancy.
When I launch the application and invoke Test, and set a breakpoint, the value for products is there and it completes without error. If I then try to invoke GetMaxQuantityByOrderID(10248), I get the error listed at bottom. Why would Test() work and the same method WITHIN Test() NOT work? I even added another (Test1(), exact same as Test except it returns string: x.ProductName, which correctly displays Queso Cabrales). It seems odd that a method that is being called within another works, but calling it directly causes an exception.
Another issue I have is that the IEnumerable GetOrders() works only if I add .ToList(). Without it (or with .AsEnumerable()), I get an error (The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.), even though lazy loading is set to False. What is the logic behind this?
IServiceTest.cs
using System.Collections.Generic;
using System.ServiceModel;
namespace WcfTestServiceLibrary
{
[ServiceContract]
public interface IServiceTest
{
[OperationContract]
IEnumerable<Orders> GetOrders();
[OperationContract]
IEnumerable<Customers> GetCustomers();
[OperationContract]
Customers GetCustomerByID(string customerID);
[OperationContract]
Orders GetOrderByID(int id);
[OperationContract]
IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id);
[OperationContract]
Order_Details GetMaxQuantityByOrderID(int id);
[OperationContract]
void Test();
}
}
ServiceTest.cs
using System.Collections.Generic;
using System.Linq;
namespace WcfTestServiceLibrary
{
public class ServiceTest : IServiceTest
{
public IEnumerable<Orders> GetOrders()
{
using (var ctx = new NWEntities())
{
return (from o in ctx.Orders.Include("Order_Details.Products").Include("Customers")
select o).ToList();
}
}
public IEnumerable<Customers> GetCustomers()
{
using (var ctx = new NWEntities())
{
return (from c in ctx.Customers
select c);
}
}
public Customers GetCustomerByID(string customerID)
{
return (from c in GetCustomers()
where c.CustomerID == customerID
select c).FirstOrDefault();
}
public Orders GetOrderByID(int id)
{
IEnumerable<Orders> orders = GetOrders();
return (from o in orders
where o.OrderID == id
select o).FirstOrDefault();
}
public IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id)
{
return GetOrderByID(id).Order_Details;
}
public Order_Details GetMaxQuantityByOrderID(int id)
{
Orders order = GetOrderByID(id);
return order == null ? null : order.Order_Details.OrderByDescending(x => x.Quantity).FirstOrDefault();
}
public void Test()
{
const int orderID = 10248;
var oq = GetMaxQuantityByOrderID(orderID);
var x = oq.Products;
}
}
}
Error:
An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/WcfTestServiceLibrary/Service1/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ClientReliableChannelBinder`1.RequestClientReliableChannelBinder`1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at IServiceTest.GetMaxQuantityByOrderID(Int32 id)
at ServiceTestClient.GetMaxQuantityByOrderID(Int32 id)
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
I had a very similar issue as you did. I found out that the Entity Framework proxy that wraps around your POCO classes is by default serialized by the WCF serializer, which cannot be deserialized on the client side since the client is not aware of the EF proxy wrapper. There were two solutions that I found. The first is to set ContextOptions.ProxyCreationEnabled to false. This prevents the EF from creating proxies for your POCO objects. The second was to instruct the WCF DataContractSerializer on the server side to use the ProxyDataContractResolver to serialize as just the POCO.
The second option can be found at http://msdn.microsoft.com/en-us/library/ee705457.aspx. Since I have just discovered these solutions I can't say which I would recommend as a general practice, although I lean to the latter, since the EF queries may be re-used by other callers from time to time that may want the objects returned with the appropriate EF proxies. Anyhow I know that's late to this question, but I hope that helps others who come across this issue.
Its the .Inculde in your LINQ-Statement.
I believe the reason for this is the basicaly resulting infinite datastructure pointing to and from "one" side to the "many" side of your relationship.
This you can observe by unfolding your datastructure, setting a breakpoint at the result of your .Include query statement in the debugger...
Observation:
Orders --> many Products, each product--> Order--> many Products and so forth
I guess wcf runns into that and gets cought up in that.
To break this chain of, you can simply avoid the pointing back in your data transfer object
by adding the ignoreDataMember Attribute
In the Many-Side of your relationship... In your case the Product....
[IgnoreDataMember]
public Order OrderFatherElement { get; set; }
This way WCF will stop the serializingattempt when reaching that childnode
#microsoft.... some potential for a fix?
Greets,
Kieredin Garbaa
For the first issue try to turn on WCF tracing on your service. Second issue with IEnumerable is caused by deffered execution. Btw. do you understand difference between IQueryable<T> and IEnumerable<T>? Do you know that your GetOrders method loads all Orders, related Customers and Products into memory? Even if you want to select single order you still load all of them in the service.
Edit:
WCF tracing will show you what happend during service or client execution - it traces WCF internals and it is essential tool for WCF development. Tutorial on WCF tracing and trace viewer.
IQueryable builds expression tree which is compiled into database query so you can't execute that query (deffered execution) outside context scope (context is responsible for database connection). You have to rewrite your methods. In your case each method has to create complete query and execute that query inside context scope. Execution of query is performed by selecting single record (like FirstOrDefault()) or by converting to list.