LINQ to SQL and open connections - c#

I've always had in my data access layer the following kind of code setup (made up example)
public static class LoadData
{
private static SomeDataContext db = new SomeDataContext();
public static void LoadData(DropDownList ddl)
{
(from ls in db.MyLookup
select ls).OrderBy(ls=>ls.theId).ToList()
.ForEach(ls=>ddl.Items.Add(new ListItem(ls.theText, ls.theValue.ToString())));
}
}
Is the DataContext "smart" enough to cleanup after itself or should I be wrapping my query with a using statement to make sure connections are closed?

You should most definitely be, at least, using a using block when accessing the database. The Data Context does not automatically open and close the connections for you. You're still responsible for your resources.
You might want to look into using the Unit of Work pattern in case you need to access the database multiple times using a single connection (related data, etc.).

Is the DataContext "smart" enough to cleanup after itself
Data Context's are designed to be used in a small scope; that of a single transaction. As such they won't release any of their resources until you dispose of them and allow the object to go out of scope. Using a single context through your entire application like this will result in the consumption of a significant amount of resources (including a network connection as well as memory (both managed and unmanaged)).
You should instead create a new data context for each LoadData call, and wrap the context in a using to ensure that it's properly disposed after each call.
As noted in comments the data context is also not thread safe, so that is yet another reason not to be re-using the same context across multiple logical transactions.

Related

Can I use MARS with EF Core to retrieve details on in a foreach

I'm not sure that the current implementation of our DAL is correct and I think that the number of connections to the DB is low with respect to what it should be.
I've noticed that there's no MARS inside the connection string
and when I try to perform multple calls on the same repository I got
System.InvalidOperationException:A second operation was started on
this context instance before a previous operation completed. This is
usually caused by different threads concurrently using the same
instance of DbContext. For more information on how to avoid threading
issues with DbContext, see
https://go.microsoft.com/fwlink/?linkid=2097913.
This means that I cannot open use the same repository for example executing an operation in parallel (for example getting some details?)
for example
foreach(var i in mainProducts) // retrieved from EF with a .ToListAsync
{
i.Details = await repo.GetDetailsFromIdAsync(i.Id);
}
I know that sometime i can just return a single object from the query, but there're some cases where I can't
Thanks

Is there any problem about create different Database contexts every time without using

Well, I would like to know what is the possible problems about use the following approach
CreateContextFactory().Create().QueryOpenConnectionCount();
instead of:
using (var context = CreateContextFactory().Create())
{
openConnectionCount = context.QueryOpenConnectionCount();
}
return openConnectionCount;
and also if there is any problem about something like:
CreateContextFactory().Create().QueryOpenConnectionCount1();
CreateContextFactory().Create().QueryOpenConnectionCount2();
CreateContextFactory().Create().QueryOpenConnectionCount3();
This is because I have some methods in a class that are open db contexts as above, I could create a using statement for them, but so I would need to pass the context for all methods, and I would also need to refactor a helper that executes a transaction using a db context (because it creates its own context internally). So what are the problems about let the code stay this way?
Often, a data-context "owns" a connection, to avoid constantly having to fetch one from the pool and initialize it. Disposing the data-context typically disposes that connection.
So: if you keep creating data-contexts without properly disposing them, you're hemorrhaging connections, at least until GC steps in and undoes the mess (releasing the unmanaged part of the connection back into the unmanaged pool, if there is an unmanaged part).
This is a bad thing, and severely limits scalability and increases the number of open connections to your database server. So yes, you should dispose your data-contexts. Extending that to the general case: you dispose any IDisposable thing that you're responsible for, when you're done with it. With perhaps a few exceptions (HttpClient, DataTable, etc).
Note that C# 8 has a slightly terser (I would say "nicer", but that is subjective; I like it a lot) syntax for this, if your using statement reaches to the end of the current scope (i.e. to the next }):
using var context = CreateContextFactory().Create();
return context.QueryOpenConnectionCount();
or even with earlier C# you can make it simpler and remove the local:
using (var context = CreateContextFactory().Create())
{
return context.QueryOpenConnectionCount();
}

Global lock and wait if something true

I have an issue where my API receives a ColumnId from outside (its purpose is to do some updates in the database). However, if two requests with the same Id try to access it, I receive an error because two transactions can't be executed over the same row.
Since I still need to execute both nonetheless, is there a way to make a Singleton or a static class that will handle these HTTP requests so that if two requests with the same ColumnId get sent to the API, the API executes the first one and then executes the second one?
public MyClass DoStuff(MyClass2 obj, HttpRequestMessage request)
{
MyClass test = new MyClass();
// .Create() creates a session with the database
using (var sc = _sessionManager.Create())
{
try
{
var anotherObj = _repository.FindForUpdate(obj.Id);
//modify anotherObj, save it to the database and set some values for `test` based on anotherObj
}
catch
{
sc.Rollback();
}
}
return test;
}
FindForUpdate executes a query similar to this:
SELECT * FROM table WHERE id = #Id FOR UPDATE
The best I can think of is to have a singleton (as stated above) that will queue and lock the using statement in DoStuff if the Id is the same, but I don't know how to do it.
It should be quite straightforward to implement a global lock either in a static class or in a class defined with a singleton lifetime in your IoC container. You could use the lock keyword for this, or one of the many other synchronization primitives offered by .Net such as the SemaphoreSlim class.
However, as pointed out by John, this scales poorly to multiple web servers, and doesn't leverage the concurrency mechanisms offered by the database. It's hard to give concrete recommendations without knowing the specifics of your database platform and data access framework, but you should probably look into either using FOR UPDATE WAIT if your database supports it, or just an optimistic concurrency mechanism with some retry logic in your application for reapplying the update after waiting a short while.
Ideally, you will also want to change any long-running blocking operations in your application to use async/await, so that the web server thread is released back to the threadpool for serving other requests.

Difference between a 'using statement' for every SqlConnection and single SqlConnection as private property in C# data layer

When implementing the repository pattern using Dapper ORM I am currently doing the following:
private readonly ConnectionStrings _connectionStrings;
private IDbConnection _db;
public CustomerRepository(IOptions<ConnectionStrings> connectionStrings)
{
_connectionStrings = connectionStrings.Value;
_db = new SqlConnection(_connectionStrings.DefaultConnection);
}
public Customer Find(int id)
{
return this._db.Query<Customer>("SELECT * FROM Contacts WHERE Id = #Id", new { id }).SingleOrDefault();
}
Can someone please tell me if I should be doing it this way or if I should be using a using statement with a new SqlConnection in every single repository function.
I am assuming my above code will need something like UnitOfWork to be effective right? And also some way of disposing the connection when done running all of the repository functions needed.
The recommended approach is to use using statements. User paulwhit explained their usage great in this answer:
The reason for the "using" statement is to ensure that the object is disposed as soon as it goes out of scope, and it doesn't require explicit code to ensure that this happens.
The essential difference between having using statements in your methods and having the connection be a class member is that the using statement makes sure that once you're done with your operations, and have exited the block, your connection is closed and disposed of properly. This removes any possibility of error on the part of the developer, and generally makes everything neater.
An important additional benefit of the using statement in this situation is that it ensures the connection is disposed of, even if there is an exception (though it is worth noting that this isn't strictly the only way to achieve this). According to the documentation:
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object.
If you were to have the connection be a class member, then an unhandled exception in the middle of a method that caused your program to exit early would possibly leave the connection open. This is of course not a good thing.
So to sum up, unless you have a very good reason not to, go with the using statement.
In general when a type implements IDisposable (and hence works with using) it can sometimes be useful to wrap it in another type, having that other type also implement IDisposable and have its Dispose() call the wrapped object, and then use using (or another mechanism to call Dispose()) on it.
The question is whether this is one of those sometimes.
It's not. In particular note that SqlConnection implements pooling behind the scenes, so (unless you explicitly opt-out in your connection string) instead of Dispose() shutting down the entire connection to the server what actually happens is that an object internal to the assembly of SqlConnection that handles the details of the connection is put into a pool to use again the next time an SqlConnection with the same connection string is opened.
This means that your application will get as efficient use of as few connections as possible over many uses of the SqlConnection class. But you are stymying that by keeping the connections out of the pool by not returning to the pool as promptly as possible.

Why should I use Using block to connect to the EntityFramework Model?

I am a new .NET developer and I am using LINQ-to-Entities for my first time. As I am practicing a lot on it, I would like to ask you about the entity framework a question that I could not find its solution on Google. Since I am connecting to the entities in my code as following:
using(MyEntities context = new MyEntities())
Why should I use Using block for connecting to the Entities? Is there any way like defining a Helper class to take care of this?
You use using statements to make sure any resources you are done with get disposed of, so they don't use any memory when they don't need to. If you would have many connections to Entity Framework (EF) open (for instance), your app could consume a whole lot of memory and cause some trouble on the machine it's running on.
A using statement calls Dispose() on an object that implements IDisposable (an interface). You could avoid using the using statement by calling Dispose() explicitly. (But you might forget, so it's easy to just use the using for an object that you want to dispose once you're done with it.)
You could setup a connection in a helper class, by, for instance, using a Singleton Pattern to make sure you only ever have one object with an Entity Connection at the most. But in the case of EF this might cause other problems with tracking by EF. You could also setup a Repository (C# EF Repository Pattern) that is the only class to open and close these connections to EF and keeps it neatly in one place.
using is a handy shortcut to say .Dispose() at the end of object's usage. It wraps your code in try-finally block, so, even if exception will occur, all object resources (like opened connection, etc.) will be disposed. This is necessary, since connection, for example, is really limited resource, and should be treated with care.
So instead of coding manually
//Define context object here
try
{
//Do some job, which might lead to exception
}
finally
{
context.Dispose();
}
you're doing just simple
using(var context = new MyEntities())
{
//Do some job, which might lead to exception
} //Resources will be disposed here
Efficiently it's same. But more easy to write.
Additionally, you can (and mostly should, it's good practice) apply using to object of any class, which implements IDisposable interface.
Some readings:
Entity Framework and context dispose
Entity Framework 4 - lifespan/scope of context in a winform application //though about winforms, still interesting discussion
http://msdn.microsoft.com/en-us/library/system.idisposable%28v=vs.110%29.aspx
Using only makes sure that your unmanaged resources will be safely disposed at the end of using block. You don't need to make manual dispose in finally block.
Normal exception handling is still necessary to organize. It's up do you, how to do it.
try
{
using(var context = new MyEntities()) //Connection is not opened yet...
{
var data = context.Collection.ToList(); //Here Entity will try to open connection.
//If it's impossible, you will have EntityException.
} //Resources will be disposed here
}
//Something about entity
catch(EntityException ex)
{
//Let's log it...
Logger.Log.Error("Some problem with entity...", ex);
//Show message, or notify user in other way
MessageBox.Show("Problem with database.");
}
//You don't know, what happened, but will check log
catch(Exception ex)
{
Logger.Log.Error("Unknown problem...", ex);
//Show message, or notify user in other way
MessageBox.Show("Problem. If it will persist, contact your admins");
}
But it's only stub. What really should be done, depends heavily on your application and db access architecture...

Categories

Resources