Entity Framework Timeouts - c#

I am getting timeouts using the Entity Framework (EF) when using a function import that takes over 30 seconds to complete. I tried the following and have not been able to resolve this issue:
I added Default Command Timeout=300000 to the connection string in the App.Config file in the project that has the EDMX file as suggested here.
This is what my connection string looks like:
<add
name="MyEntityConnectionString"
connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
res://*/MyEntities.msl;
provider=System.Data.SqlClient;provider connection string="
Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
MultipleActiveResultSets=True;Default Command Timeout=300000;""
providerName="System.Data.EntityClient" />
I tried setting the CommandTimeout in my repository directly like so:
private TrekEntities context = new TrekEntities();
public IEnumerable<TrekMatches> GetKirksFriends()
{
this.context.CommandTimeout = 180;
return this.context.GetKirksFriends();
}
What else can I do to get the EF from timing out? This only happens for very large datasets. Everything works fine with small datasets.
Here is one of the errors I'm getting:
System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
OK - I got this working and it's silly what happened. I had both the connection string with Default Command Timeout=300000 and the CommandTimeout set to 180. When I removed the Default Command Timeout from the connection string, it worked. So the answer is to manually set the CommandTimeout in your repository on your context object like so:
this.context.CommandTimeout = 180;
Apparently setting the timeout settings in the connection string has no effect on it.

There is a known bug with specifying default command timeout within the EF connection string.
http://bugs.mysql.com/bug.php?id=56806
Remove the value from the connection string and set it on the data context object itself. This will work if you remove the conflicting value from the connection string.
Entity Framework Core 1.0:
this.context.Database.SetCommandTimeout(180);
Entity Framework 6:
this.context.Database.CommandTimeout = 180;
Entity Framework 5:
((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;
Entity Framework 4 and below:
this.context.CommandTimeout = 180;

If you are using a DbContext, use the following constructor to set the command timeout:
public class MyContext : DbContext
{
public MyContext ()
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 1 * 60; // value in seconds
}
}

If you are using DbContext and EF v6+, alternatively you can use:
this.context.Database.CommandTimeout = 180;

If you are using Entity Framework like me, you should define Time out on Startup class as follows:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));

Usually I handle my operations within a transaction. As I've experienced, it is not enough to set the context command timeout, but the transaction needs a constructor with a timeout parameter. I had to set both time out values for it to work properly.
int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}
At the end of the function I set back the command timeout to the previous value in prevto.
Using EF6

I know this is very old thread running, but still EF has not fixed this. For people using auto-generated DbContext can use the following code to set the timeout manually.
public partial class SampleContext : DbContext
{
public SampleContext()
: base("name=SampleContext")
{
this.SetCommandTimeOut(180);
}
public void SetCommandTimeOut(int Timeout)
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
objectContext.CommandTimeout = Timeout;
}
}

In .Net Core (NetCore) use the following syntax to change the timeout from the default 30 seconds to 90 seconds:
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
this.Database.SetCommandTimeout(90); // <-- 90 seconds
}
}

This is what I've fund out. Maybe it will help to someone:
So here we go:
If You use LINQ with EF looking for some exact elements contained in the list like this:
await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();
everything is going fine until IdList contains more than one Id.
The “timeout” problem comes out if the list contains just one Id. To resolve the issue use if condition to check number of ids in IdList.
Example:
if (IdList.Count == 1)
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();
}
else
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();
}
Explanation:
Simply try to use Sql Profiler and check the Select statement generated by Entity frameeork. …

For Entity framework 6 I use this annotation and works fine.
public partial class MyDbContext : DbContext
{
private const int TimeoutDuration = 300;
public MyDbContext ()
: base("name=Model1")
{
this.Database.CommandTimeout = TimeoutDuration;
}
// Some other codes
}
The CommandTimeout parameter is a nullable integer that set timeout
values as seconds, if you set null or don't set it will use default
value of provider you use.

Adding the following to my stored procedure, solved the time out error by me:
SET NOCOUNT ON;
SET ARITHABORT ON;

There are 2 timeout parameters you can set in connection string
Timeout=300;CommandTimeout=300;
Host=localhost;Port=5432;database=mydatabase;username=postgres;password=postgres;Timeout=300;CommandTimeout=300;
one for command and one for connection.

Related

ASP.NET C#: Entity updating is being blocked

Experiencing an issue about updating mysql DB through EF. It's not the first time I'm dealing with it, so I had some ideas about why isn't my data getting changed. I tried changing an element in goods array; tried editing an object, recieved through LINQ-request (seen some examples of this method); made some attempts on marking element found in the database before editing (like EntityState and Attach()). Nothing of these made any difference, so I tried removing <asp:UpdatePanel> from Site.Master to see what happens (responsive for postback blocking to prevent page shaking on update), but nothing changed (while btnRedeemEdit.IsPostBack having its default value).
Code below is the function I use for updates.
protected void btnRedeemEdit_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["id"]))
{
var db = new GoodContext();
var goods = db.Goods.ToList();
Good theGood = goods.FirstOrDefault(x => x.Id == int.Parse(Request.QueryString["id"]));
//db.Goods.Attach(theGood);//No effect
//db.Entry(theGood).State = System.Data.Entity.EntityState.Modified; //No effect
if (theGood != default)
{
theGood.AmountSold = GetInput().AmountSold;
theGood.APF = GetInput().APF;
theGood.Barcode = GetInput().Barcode;
theGood.Description = GetInput().Description;
theGood.ImagesUrl = GetInput().ImagesUrl;//"https://i.pinimg.com/564x/2d/b7/d8/2db7d8c53b818ce838ad8bf6a4768c71.jpg";
theGood.Name = GetInput().Name;
theGood.OrderPrice = GetInput().OrderPrice;
theGood.Profit = GetInput().Profit;
theGood.RecievedOn = GetInput().RecievedOn;//DateTime.Parse(GetInput().RecievedOn).Date.ToString();
theGood.TotalAmount = GetInput().TotalAmount;
theGood.WeightKg = GetInput().WeightKg;
//SetGoodValues(goods[editIndex],GetInput());//Non-working
db.SaveChanges();
Response.Redirect("/AdminGoods");
}
else Response.Write($"<script>alert('Good on ID does not exist');</script>");
}
else Response.Write($"<script>alert('Unable to change: element selected does not exist');</script>");
}
Notice, that no alerts appear during execution, so object in database can be found.
Are there any more things, that can be responsible for blocking database updates?
A few things to update & check:
Firstly, DbContexts should always be disposed, so in your case wrap the DbContext inside a using statement:
using (var db = new GoodContext())
{
// ...
}
Next, there is no need to load all goods from the DbContext, just use Linq to retrieve the one you want to update:
using (var db = new GoodContext())
{
Good theGood = db.Goods.SingleOrDefault(x => x.Id == int.Parse(Request.QueryString["id"]));
if (theGood is null)
{
Response.Write($"<script>alert('Good on ID does not exist');</script>");
return;
}
}
The plausible suspect is what does "GetInput()" actually do, and have you confirmed that it actually has the changes you want? If GetInput is a method that returns an object containing your changes then it only needs to be called once rather than each time you set a property:
(Inside the using() {} scope...)
var input = GetInput();
theGood.AmountSold = input.AmountSold;
theGood.APF = input.APF;
theGood.Barcode = input.Barcode;
theGood.Description = input.Description;
// ...
db.SaveChanges();
If input has updated values but after calling SaveChanges you aren't seeing updated values in the database then there are two things to check.
1) Check that the database connection string at runtime matches the database that you are checking against. The easiest way to do that is to get the connection string from the DbContext instance's Database.
EF 6:
using (var db = new GoodContext())
{
var connectionString = db.Database.Connection.ConnectionString; // Breakpoint here and inspect.
EF Core: (5/6)
using (var db = new GoodContext())
{
var connectionString = db.Database.GetConnectionString();
Often at runtime the DbContext will be initialized with a connection string from a web.config / .exe.config file that you don't expect so you're checking one database expecting changes while the application is using a different database / server. (More common than you'd expect:)
2) Check that you aren't disabling tracking proxies. By default EF will enable change tracking which is how it knows if/when data has changed for SaveChanges to generate SQL statements. Sometimes developers will encounter performance issues and start looking for ways to speed up EF including disabling change tracking on the DbContext. (A fine option for read-only systems, but a pain for read-write)
EF6 & EF Core: (DbContext initialization)
Configuration.AutoDetectChangesEnabled = false; // If you have this set to false consider removing it.
If you must disable change tracking then you have to explicitly set the EntityState of the entity to Modified before calling SaveChanges():
db.Entry(theGood).State = EntityState.Modified;
db.SaveChanges();
Using change tracking is preferable to using EntityState because with change tracking EF will only generate an UPDATE statement if any values have changed, and only for the values that changed. With EntityState.Modified EF will always generate an UPDATE statement for all non-key fields regardless if any of them had actually changed or not.

EF6: DbContext.Database.Connection.ConnectionString changes after calling ExecuteSqlCommand

I am observing a weird behavior in EF6 DbContext. My custom DbContext class reads its connection string from my App.config:
public partial class WorkobjectContext : DbContext
{
public WorkobjectContext()
: base("name=MainConnectionString")
{
// Set the initializer to null to disable intializtion otherwise EF tries to create the table if it does not exist (CreateDatabaseIfNotExists)
Database.SetInitializer<WorkobjectContext>(null);
}
}
As I am using the same connection string for my Ado.NET functions, I try to read the connection string out of DbContext:
var connectionstring = this.MyContext.Database.Connection.ConnectionString;
But now I am observing that this.MyContext.Database.Connection.ConnectionString changes as I call ExecuteCommand:
...
Console.WriteLine(this.WorkobjectContext.Database.Connection.ConnectionString);
// Output: DATA SOURCE=XXXX:1000/XXXX.XXXX;PASSWORD=MyPassword;USER ID=MyUserId
var ret = this.WorkobjectContext.Database.ExecuteSqlCommand(
"BEGIN WPK_Inbox.Check_WOB_User(:pn_UserID, :pn_WOBID, :pn_Return, :pvErrorMsg, :pnErrorCode); end;",
new object[]
{
userIdParameter,wobIdParameter,returnValueParameter,errorMsgParameter,errorCodeParameter
}
);
Console.WriteLine(this.WorkobjectContext.Database.Connection.ConnectionString);
// Output: DATA SOURCE=XXXX:1000/XXXX.XXXX;PUSER ID=MyUserId
As you can see, after calling ExecuteSqlCommand the connection string changes and the password part disappears.
Why is this happening? Is this a bug?

Executing SQL store procedure by EF Core 2.2 gets a timeout while executing it successfully in SQL Server Management

I've got a strange behaviour. When I trying to execute SQL store procedure by EF Core 2.2. I get a timeout (30 seconds). But when I execute the same procedure within SQL Server Management Studio it runs successfully - it runs it about 1 or 2 sec.
UPDATE: This problem occured around 2 month ago. Before that the service was able to run this proc.
Here is a DbContext that I use:
public class MyContext : DbContext
{
public MyContext(string connectionString)
: base(new DbContextOptionsBuilder().UseSqlServer(connectionString).Options)
{
}
// some DbSets omitted here ...
public async Task<string> ProcExecuteAsync(string login, string xml)
{
// get some data from db (omitted)
var xmlParameter = new SqlParameter("#XML", SqlDbType.Xml) { Value = xml };
var xmlOutputParameter = new SqlParameter("#XMLoutput", SqlDbType.Xml) { Direction = ParameterDirection.Output };
await Database.ExecuteSqlCommandAsync(
"MyProc_set #idUser=#idUser,#XML=#XML,#XMLoutput=#XMLoutput OUT",
new SqlParameter[] { userIdParameter, xmlParameter, xmlOutputParameter });
return (string)xmlOutputParameter.Value;
}
}
Then I have a handler (I use Mediator library):
public class AddToClientCommandHandler : IRequestHandler<AddToClientCommand, AddToClientResponse>
{
private readonly IContextBuilder _contextBuilder;
public AddToClientCommandHandler(IContextBuilder contextBuilder)
{
_contextBuilder = contextBuilder;
}
public async Task<AddToClientResponse> Handle(AddToClientCommand command, CancellationToken cancellationToken)
{
using (var context = _contextBuilder.CreateMyContext())
{
// getting some data from db (omitted)
// generate xmlRequest (omitted)
var result = await context.ProcExecuteAsync(command.Login, xmlRequest);
return new AddToClientResponse(result);
}
}
}
Here is a ContextBuilder:
public class ContextBuilder : IContextBuilder
{
private readonly IOptions<ConnectionStrings> _connectionStrings;
public ContextBuilder(IOptions<ConnectionStrings> connectionStrings)
{
_connectionStrings = connectionStrings;
}
public MyContext CreateMyContext()
{
var result = new MyContext(_connectionStrings.Value.Entities);
return result;
}
}
And I register it like this:
public static class ApplicationContextBuilderExtension
{
public static void AddApplicationContextBuilder(this IServiceCollection services)
{
services.AddSingleton<IContextBuilder, ContextBuilder>();
}
}
Is it possible that the problem comes from that I use AddSingleton when I register ContextBuilder?
Can someone point me up to how and where investigate the problem?
Is it possible that the problem comes from that I use AddSingleton when I register
ContextBuilder?
No, as the one method in ContextBuilder is not doing db operations and is no returning the same context all the time.
But when I execute the same procedure within SQL Server Management Studio it runs
successfully
And how long does it take? To my knowledge SSMS does not impose and timeout limit, which would tell you why you do not get a timeout. EfCore is limited to 30 seconds UNLESS you CHANGE IT - which is trivial as per documentation, but it must be done.
The concept here being that SSMS is way more used for bulk operations than EfCore where a 30 second operation can be considered an error - and in those rare cases you want/need a longer timeout, reconfigure the dbcontext.
I have got the same issue. I went through the following link:
Stored procedure slow when called from web, fast from Management Studio
I have modified sp like this:
ALTER PROCEDURE [dbo].[sproc]
#param1 int,
AS
SELECT * FROM Table WHERE ID = #param1
to
ALTER PROCEDURE [dbo].[sproc]
#param1 int,
AS
DECLARE #param1a int
SET #param1a = #param1
SELECT * FROM Table WHERE ID = #param1a
For me, it is working fine.

Entity Framework 5 failure while adding a new record of a specific object

I truly do not know how to solve this issue , i am used to add or remove object using entity framework in this way always .
i run my app in debug mode and followed it .
the debugger continue with no issues at all , then i look into database for a new record , but nothing happen at all .
private dbClinics _context;
public dbClinics context { get { return new dbClinics(); } set { _context = value; } }
#endregion
private void _AddProfession(string ProfessionName)
{
if (!context.Professions.Any(x => x.ProfessionName.ToLower().Equals(ProfessionName.ToLower())))
{
Profession profession = new Profession();
profession.ProfessionName = ProfessionName;
context.Professions.Add(profession);
context.SaveChanges();
}
}
Here is the connection string :
<add name="dbClinics" connectionString="metadata=res://*/ADO.dbClinics.csdl|res://*/ADO.dbClinics.ssdl|res://*/ADO.dbClinics.msl;provider=System.Data.SqlClient;provider connection string="data source=mld\markinstance;initial catalog=beta_clinics;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /></connectionStrings>
And Sure i have make sure that the table auto increment its primary key
Pay attention to your context property it recreates dbcontext for each call so the context you add the entity is not the same as the one you call save changes
Please manage dbcontext life cycle - preferably by using using statement

Enterprise Library 5.0 and Command Timeout

I am using following code and want to know whether we require to set command timeout if using CreateSprocAccessor of enterprise library , if not then how timeout is being managed?
var accessor = _sqlDatabase.CreateSprocAccessor<xyz>("uspGetxyz",
new xyzParameters(_sqlDatabase),
MapBuilder<xyz>.MapAllProperties().Build());
//Execute the accessor to obtain the results
var Data = accessor.Execute();
xyzList = Data.ToList<xyz>();
I have started using Microsoft Enterprise Library long back where in normal case the DB operation calls using provided methods of “Database” class fulfill the need. In some case, for the long running query, developer wants to set CommandTimeout property of SqlCommand (or DbCommand) class. This will allow query to be executed long time as value set in command timeout.
By default Data Access Application block does not support/take simple CommandTimeout parameter in method calls (there are many workaround samples available on net). To achieve the same with minimal changes, I have added a simple function named “WithCommandTimeOut” taking timeOutSecond parameter in “Microsoft.Practices.EnterpriseLibrary.Data.Database” class which returns same instance of “Database” class. Refer updated code snippet below for code changes. Hope this will solve timeout Problem.
//Class Level Static Variables
//Used to reset to default after assigning in "PrepareCommand" static method
static int DEFAULT_COMMAND_TIMEOUT_RESET = 30;
//Default value when "WithCommandTimeOut" not called
static int COMMAND_TIMEOUT_FOR_THIS_CALL = DEFAULT_COMMAND_TIMEOUT_RESET;
public Database WithCommandTimeOut(int timeOutSeconds)
{
COMMAND_TIMEOUT_FOR_THIS_CALL = timeOutSeconds;
return this;
}
protected static void PrepareCommand(DbCommand command, DbConnection connection)
{
if (command == null) throw new ArgumentNullException("command");
if (connection == null) throw new ArgumentNullException("connection");
//Here is the magical code ----------------------------
command.CommandTimeout = COMMAND_TIMEOUT_FOR_THIS_CALL;
//Here is the magical code ----------------------------
command.Connection = connection;
//Resetting value to default as this is static and subsequent
//db calls should work with default timeout i.e. 30
COMMAND_TIMEOUT_FOR_THIS_CALL = DEFAULT_COMMAND_TIMEOUT_RESET;
}
Ex.
Database db = EnterpriseLibraryContainer.Current.GetInstance(Of Database)("SmartSoftware");
db.WithCommandTimeOut(0).ExecuteDataSet(CommandType.Text, query);
I can't believe it what blunder enterprise library team has made, they have not given any way to set command time out in case of Accessor, it is a know issue with them
http://entlib.codeplex.com/workitem/28586
cant believe it, i have developed whole project and just came to know this a know issue :-(wtf
We can update this in the connection string, increase Connection Timeout=1000;
You can modify DbCommand timeout in your xyzParameters class in AssignParameters method:
public void AssignParameters(
System.Data.Common.DbCommand command, object[] parameterValues)
{
command.CommandTimeout = 0;
...
}
Volla!!! i have made changes in source code of Enterprise library, added a new "execute" method which will take timeOut paramerter, in Sproc accessors class and used these binaries in my project

Categories