I came in late to a project developed with asp.net mvc, EF6 and SQL Server. The code is a mess and they use linq everywhere to retrieve data. Now they are about to add a second SQL Server for a different country/language. I can't seem to get my head around the DbContext / IDbConnectionFactory stuff but can I do it the easy way here and override something, somewhere, so I can insert the right connections string depending on a selected culture?
To simplify:
I want to override DbContext so when it is created I can insert a connection string depending on a session value (for example) without specifying a connection string in the constructor.
How would I achieve this? Doing it the right way of course..
Thx!
/Mike
Your DBContext must have been created as a partial class. Create you second partial class next to it, and add a static constructor method there
public static DBContext Create()
Implement the logic inside it, and use this constructor everywhere you need context to be created. This will be kind of factory method. You can define your connection strings in config file and simply create context based on connection string name depending on certain conditions.
What you're trying to achieve is, to some extend, a database sharding architecture.
There are multiple resources on the internet you may want to have a look at to get acquainted with db shards...
i.e. http://www.4tecture.ch/blog/sql-azure-federations-with-entity-framework
Related
I was given a few dozen legacy SQL statements that are each hundred(s) of lines long. Each SQL is mapped to code with its own unique POCO in a shared Models project.
For example, the SQL Select Name, Birthday From People has an equivilent POCO in the Models project:
public class BirthdayPerson : SqlResultBase {
public string Name { get; set; }
public datetime Birthday { get; set; }
//SqlResultBase abstraction:
public string HardcodedSql { get {
return "Select Name, Birthday From People";
}}
}
In my DAL, I have a single generic SQL runner whose <T> represents the POCO for the SQL. So my business logic can call GetSqlResult<BirthdayPerson>():
public IEnumerable<T> GetSqlResult<T>() where T : SqlResultBase, new() {
return context.Database.SqlQuery<T>((new T()).HardcodedSql);
}
The problem is that my Models library is used across the application, and I don't want SQL exposed across the application in that HardcodedSql property.
This is the architecture I'm using:
At first you have to separate your model (i.e. POCOs) from the SQL which actually belongs to the DAL. Inversion of Control is right way to do this. Instead of generic sql runner it is better to register mappings in the IoC container from abstract repositores (e.g. IRepository<MyPOCO>) to implementations that contain the SQLs.
EDIT: To be more concrete, a possible solution:
Place all SQLs to a separate file(s) inside DAL, for example to a set of embedded resource files with name convention, e.g. Legacy-{0}.sql where {0} is name of the POCO.
Create a generic implementation of legacy repository that uses POCO name as a key and picks corresponding Legacy-{0}.sql file from the resource set. Note that there may be other implementations as well that use other data access techniques, like ORM.
In the composition root register explicitly all mappings from the legacy POCOs to the legacy implementation: IRepository<MyPOCO1> => LegacyRepo<MyPOCO1>; IRepository<MyPOCO2> => LegacyRepo<MyPOCO2>; etc. Moreover you may register other mappings from non-legacy entities to other implementations of repository.
The simplest solution would be to make HardcodedSql internal instead of public so it's only visible within a DAL Project. If the DAL is a separate project from the model you could use InternalsVisibleTo to expose it to that project. This assumes you can configure your project structure accordingly.
I suggest perhaps two possible ways of dealing with the question.
As for the first method, I would rather change how the sql is accessed and wrap the call locally in a method. So the class may have a function called public IEnumerable GetFromSql() you could pass in a context, or create a new one, I am not sure how you have setup EF in your project. this way you never publically expose the raw sql, as you would rather make it a private variable or local constant perhaps and simply access it from within the function.
As a second option, and I have actually done this and it turned out pretty great, was I moved all the sql to views and used EF to access them. That way there was no sql pollution in my code.
Seeing that the models already exists, the result from calling the views would match the types that you already have.
I would like to learn more about creating a Database Entity (Connection?).
Coming from PHP/MySQL, i was creating only one connection and was reusing that over and over using a connection pool.
I noticed in MVC, I create new db entity almost every chance I get. Is this really the correct way to do so in real world example?
For example, I have a code that tells the user how many unread messages they have left on every refresh/page view. It goes like this:
public int UnreadMessages()
{
using (dbEntities db = new dbEntities())
{
return db.messages.Select(M => M.status == "Unread").Count();
}
}
On my _Layout.html, I have a line that calls this code. So, this is being executed on every request. The way I look at it, this is terrible way of doing it because I keep creating a new connection? or maybe this is the way it was supposed to be done on MVC.
Could someone please explain to me, the best way of doing this? or maybe provide some links that may help me understand this better?
P.S. I am also not too sure how db connection on MVC works. Wether 1 connection is made and a new db entity(Not a connection, rather just a call?) is created on requests or a new brand new connection is made on requests.
Two things, Entity framework uses underlying ADO.NET which supports powerful connection pooling, and connections to database are closed instantly by context. So you don't need to worry about connection pooling.
However, it is not good idea to create and destroy context every time for single operation. Ideally only one context should be created for entire lifecycle of a request. Since creating and destroying context is little costly it does affect performance at high load.
Controller has OnDispose method, and this is how you can easily implement it,
public abstract class DBController : Controller {
public MyDbContext DbContext { get; private set; }
public DBController() {
DbContext = new ...
HttpContext.Items["DbContext"] = DbContext;
}
protected override void OnDispose() {
DbContext.Dispose();
}
}
And your every Controller should be derived from DBController. And in Layout file you can use same context by retrieving HttpContext.Items["DbContext"]
This way same context will be used for entire request. And yes, for every request new context will be created. EF is not designed to be thread safe and should not be reused for different requests.
In the mvc world, views (including layout) should only use data from the model or include partial views with RenderAction() that get their models from other actions.
You ask about connections and EF though, and while opening and disposing objects frequently isn't great you need to understand that EF has its own connection pool, so if your action calls a bunch of methods that all create and dispose their own dbEntities() object, only one connection to the actual database will be used.
In my opinion, it's recommended to use using to create new instance as it will automatically close connection after the connection and dispose the instance.
If you want to use a Global variable, you need to make sure to open and close db connection in each method, then it still be fine.
However, the bad thing that you are doing is to call Database connection from your _Layout.html, that is the view, should only render the view; not to connect to DB.
First I want to explain my situation in a few sentences:
- I have a number of, what I call them, lookup-tables. This means I want all values in there to be unique. For example a lookup-table for CPU models with a name and a GUID.
public partial class CPUModel : EntityObject
{
public Guid Id {}
public String Name{}
}
The entities are safed in a SQL CE database with the help of Entity Framework and C#
I have made a CRUDManager which helps me to Select, Insert, Update and Delete Entities.
All these Operations work with a ReaderWriterLockSlim to secure against problems with multithreading.
Now there should be some sort of GetOrCreate Method where I can say GetOrCreate(cpuModelName) and this gives me a saved CPUModel, either already existing or new created. This method should also work with the ReaderWriterLockSlim.
So I would want to implement this method on CRUDManager.
Do you think I'm on the right track or would you place this directly on the CPUModel (or even somewhere else?
Thank you very much :)
CRUDManager is a good place for it. I would just look the value up (ideally via a Lookup() type function, and if it exists, select it. If not, call Create() or whatever function you have defined to create it.
It sounds like you want a dictionary. I recommend reading about it here.
I have some code which forms a database-centric class which performs CRUD operation. Insert() and Select() methods use the same connection string. At the moment, both methods are repetitive by repeating the standard bit of setting up a SqlConnection.
How best should this be refactored? Should I have a property for SqlConnection?
Thanks
Pull all your DB operations out into a single class, and pass the class to the objects that need it. You can do this via constructor injection (each new object gets an IDBProvider passed to it which it then uses for database operations).
Something like this:
public interface IDBProvider {
// ... list of DB operations you care about
List<Products> GetProducts(string vendor)
}
public class SomeWorkerClass {
private IDBProvider dbConnection;
public SomeWorkerClass(IDBProvider dbProvider) {
dbConnection = dbProvider;
}
public void SomeFunction() {
List<Products> = dbConnection.GetProducts("test");
}
}
There are lots of frameworks that do this kind of stuff for you, like NHibernate, but in some cases its just as easy to roll your own (upgrading existing code, organizations that dont want external framework dependencies, etc).
I usually do it one of two ways.
A class that contains static methods and properties to connect to a database. I can then use it in any other class I need.
A SqlConnection property in a class that connects to databases. I then inject the connection from the controlling class when I need it.
By far the first option is used most frequently. The only issue is that if the database server changes, I need to recompile the class. We only have one database server, though, and it doesn't change that often, so it really isn't that much of an issue.
The good thing about the second option is that it's a lot more flexible; if the server, user, or password changes it's as simple as updating that information in the controlling class.
This depends on your application. As far as I'm concerned: No. You might want to add a new method to set up the connection (that might even be a good idea), but a connection as field/property sounds like "I open a connection for the whole lifetime of my form", which is evil in my world.
Create a helper method and write something like
using (var connection = CreateSqlConnection()) {
// Do the operations here
}
I have a Database class which contanins the follwing methods:
public bool ExecuteUDIQuery(string query) // UDI = Update Delete Insert
public bool ExecuteSelectQuery(string query)
public bool ExecuteSP(string sp, string[,] parms)
public int ExecuteSPReturnValue(string sp, string[,] parms)
The results of the methods are stored in private datasets or datatables. These objects are defined as getters.
There're about 10 classes which use the Database class. Every class creates an object of the class Database. Now i was thinking to make the Database class static. Is this a good idea? If so, why? Of not, why not?
If I understand, the database class has some properties that store the result of the query? If so, you cannot make them static, since that is not thread-safe. If the result of a query is stored in these properties, what would happen if a second query would execute right after the first? It would be stored in the same static variable. The same goes for a web application: the result of another user browsing the site would change the results of the first user.
EDIT: To summarize, do NOT make the class static when you store the result of the queries in static variables, especially not when the class is used in a website, as the properties value will be shared amongst all visitors of your website. If 20 visitors do a query at the same time, visitor 1 will see the results of visitor 20's query.
In your specific example, I'd advise against making the class static: you're keeping state in the Database class, and by making the class static, that state will be shared amongst all classes using your Database. In your current setup, each Database instance keeps its own state, so there's no problem with Database calls interfering with each other.
If you'd refactor the Database class to return the datasets when doing a method call, you'd be fine making it static: there would be no stateful information left in the Database class.
But since this is not the case: no, don't make the class static.
In addition to the others comments about thread safety there is also the issue of paralellization. In your case you won't be able to open several connections to the database at the same time and you won't be able to perform multiple paralell queries, even if thread safety of the results isn't an issue.
So I agree with the others, don't make a static class out of it.
Making the class static may be convenient, but creating new instances of it probably won't be an expensive operation so there probably isn't much to gain performance-wise either.
Edit:
I saw in a comment that you want to use your class on a web site. In that case you REALLY shouldn't do this. With a static database class you will only be able to safely serve one request at any time, and that is not what you want.
It depends on what kind of database or ORM that you're using. But in my experience it's seemed like a good idea but ended up shafting me. Here's how it did for me in LINQ-to-SQL:
I had a repository class that had a static variable to a data context. It worked at first, but when I had to make many more repository classes I ended up getting bugs as I hacked along. It turns out that data context in LINQ-to-SQL caches up all results and there is no way to refresh them. So if you added a post in a table in one context, it won't show up in other that cached that table. The solution was to remove the static modifier and let the repository create the context in the constructor. Since the repository classes were constructed as they were used, so would a fresh new data context.
You could argue that static variables leaves less footprint in memory, but the footprint for a data context is quite small to begin with and will be garbage collected in the end.
Contrary to the answer post.
I've built a webframework with a static database access it works great and gives great performance.
You can check out the source code at http://www.codeplex.com/Cubes
If you are just executing queries against the DB, then yes make it static. You only have to create an instance if this object needs to keep some sort of state.
If you have a static method you need to keep track of instances when you open and close the database.
So what you probably want to do is have a static Method called instance or current instance. And within you create a new instance of your db-class returning it in the static method.
Your methods good for static usage. I think, you have no trouble to convert them to static methods for now.
but later maybe you will need to manage transaction. leaving the transaction management to a class is saves lots of time I think. and this scenario is best fits with a nonstatic class.