How to configure Entity Framework to use different connection string when executing migrations and when working with the database.
The reason for that is quite simple, I do not want to have sa login for the website, but I want to be able to execute migrations.
After not finding anything on the web for how to do that, the Object Explorer helped.
The EF Migration Configuration class (where AutomaticMigrationsEnabled = true is set)
has also a property named TargetDatabase.
This can be set to whatever connection string you want like so:
TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(
ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString,
ConfigurationManager.ConnectionStrings["ConnString"].ProviderName);
I have a web api project that I'm building on an N-Tier system. Without causing too many changes to the overall system, I will not be touching the data server that has access to the database. Instead, I'm using .NET remoting to create a tcp channel that will allow me to send requests to the data server, which will then query the database and send back a response object.
On my application, I would like to use entity framework to create my datacontexts (unit of work), then create a repository pattern that interfaces with those contexts, which will be called by the web api project that I created.
However, I'm having problems with entity framework as it requires me to have a connection with the database. Is there anyway I can create a full entity framework project without any sqlconnections to the database? I just need dbcontexts, which I will be mapping my response objects and I figure that EF would do what I needed (ie help with design, and team collabs, and provide a nice graphical designer); but it throws an error insisting that I need a connection string.
I've been searching high and low for tutorials where a database is not needed, nor any sql connection string (this means no localdb either).
Okay as promised, I have 3 solutions for this. I personally went with #3.
Note: Whenever there is a repository pattern present, and "datacontext" is used, this is interpreted as your UnitOfWork.
Solution 1: Create singletons to represent your datacontext.
http://www.breezejs.com/samples/nodb
I found this idea after going to BreezeJS.com's website and checked out their samples. They have a sample called NoDb, which allows them to create a singleton, which can create an item and a list of items, and a method to populate the datacontext. You create singletons that would lock a space in memory to prevent any kind of thread conflicts. Here is a tid bit of the code:
//generates singleton
public class TodoContext
{
static TodoContext{ }
private TodoContext() { }
public static TodoContext Instance
{
get
{
if (!__instance._initialized)
{
__instance.PopulateWithSampleData();
__instance._initialized = true;
}
return __instance;
}
}
public void PopulateWithSampleData()
{
var newList = new TodoItem { Title = "Before work"};
AddTodoList(newList);
var listId = newList.TodoListId;
var newItem = new TodoItem {
TodoListId = listId, Title = "Make coffee", IsDone = false };
AddTodoItem(newItem);
newItem = new TodoItem {
TodoListId = listId, Title = "Turn heater off", IsDone = false };
AddTodoItem(newItem);
}
//SaveChanges(), SaveTodoList(), AddTodoItem, etc.
{ ... }
private static readonly Object __lock = new Object();
private static readonly TodoContext __instance = new TodoContext();
private bool _initialized;
private readonly List<TodoItem> _todoLists = new List<TodoItem>();
private readonly List<KeyMapping> _keyMappings = new List<KeyMapping>();
}
There's a repository included which directs how to save the context and what needs to be done before the context is saved. It also allows the list of items to be queryable.
Problem I had with this:
I felt like there was higher maintenance when creating new datacontexts. If I have StateContext, CityContext, CountryContext, the overhead of creating them would be too great. I'd have problems trying to wrap my head around relating them to each other as well. Plus I'm not too sure how many people out there who agree with using singletons. I've read articles that we should avoid singletons at all costs. I'm more concerns about anyone who'd be reading this much code.
Solution 2: Override the Seed() for DropCreateDatabaseAlways
http://www.itorian.com/2012/10/entity-frameworks-database-seed-method.html
For this trick, you have to create a class called SampleDatastoreInitializer that inherits from System.Data.Entity.DropCreateDatabaseAlways where T is the datacontext, which has a reference to a collection of your POCO model.
public class State
{
[Key()]
public string Abbr{ get; set; }
public string Name{ get; set; }
}
public class StateContext : DbContext
{
public virtual IDbSet<State> States { get; set; }
}
public class SampleDatastoreInitializer : DropCreateDatabaseAlways<StateContext>
{
protected override void Seed (StateContext context)
{
var states = new List<State>
{
new State { Abbr = "NY", Name = "New York" },
new State { Abbr = "CA", Name = "California" },
new State { Abbr = "AL", Name = "Alabama" },
new State { Abbr = "Tx", Name = "Texas" },
};
states.ForEach(s => context.States.Add(s));
context.SaveChanges();
}
}
This will actually embed the data in a cache, the DropCreateDatabaseAlways means that it will drop the cache and recreate it no matter what. If you use some other means of IDatabaseInitializer, and your model has a unique key, you might get an exception error, where you run it the first time, it works, but run it again and again, it will fail because you're violating the constraints of primary key (since you're adding duplicate rows).
Problem I had with this:
This seems like it should only be used to provide sample data when you're testing the application, not for production level. Plus I'd have to continously create a new initializer for each context, which plays a similar problem noted in solution 1 of maintainability. There is nothing automatic happening here. But if you want a way to inject sample code without hooking up to a database, this is a great solution.
Solution 3: Entity framework with Repository (In-memory persistence)
I got this solution from this website:
http://www.roelvanlisdonk.nl/?p=2827
He first sets up an edmx file, using EF5 and the code generator templates for EF5 dbcontexts you can get from VS extension libraries.
He first uses the edmx to create the contexts and changes the tt templates to bind to the repository class he made, so that the repository will keep track of the datacontext, and provide the options of querying and accessing the data through the repository; in his website though he calls the repository as MemoryPersistenceDbSet.
The templates he modified will be used to create datacontexts that will bind to an interface (IEntity) shared by all. Doing it this way is nice because you are establishing a Dependency Injection, so that you can add any entity you want through the T4 templates, and there'd be no complaints.
Advantage of this solution:
Wrapping up the edmx in repository pattern allows you to leverage the n-tier architecture, so that any changes done to the backend won't affect the front end, and allows you to separate the interface between the front end and backend so there are no coupled dependencies. So maybe later on, I can replace my edmx with petapoco, or massive, or some other ORM, or switch from in-memory persistence to fetching data from a database.
I followed everything exactly as explained. I made one modification though:
In the t4 template for .Context.tt, where DbSetInConstructor is added, I had the code written like this:
public string DbSetInConstructor(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
“this.{1} = new BaseRepository();”,
_typeMapper.GetTypeName(entitySet.ElementType), entitySet);
}
Because in my case I had the entityset = Persons and entityname = Person. So there’d be discrepancy. But this should cover all bases.
Final step:
So whether you picked solution 1, 2, or 3. You have a method to automatically populate your application. In these cases, the stubs are embedded in the code. In my case, what I've done is have my web server (containing my front end app), contact my data server, have the data server query the database. The data server will receive a dataset, serialize it, and pass it back to the web server. The web server will take that dataset, deserialize it, and auto-map to an object collection (list, or enumberable, or objectcollection, etc).
I would post the solutions more fully but there's way too much detail between all 3 of these solutions. Hopefully these solutions would point anyone in the right direction.
Dependency Injection
If anyone wants some information about how to allow DI to api controllers, Peter Provost provides a very useful blog that explains how to do it. He does a very very good job.
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
few more helpful links of repository wrapping up edmx:
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
http://www.codeproject.com/Articles/688929/Repository-Pattern-and-Unit-of
Using an EF model in the Models folder in my MVC 4 project, I succeeded to display data in a razor view using a coded class named Prod and a controller method as next:
public ActionResult Index()
{
IEnumerable<Prod> Pr = from p in db.Products
select new Prod
{
ProductId = p.ProductID,
ProductName = p.ProductName
};
return View(Pr);
}
Now I am trying to do the same thing using a model in a class library instead of the current one, so I added to my solution a new class library, added then a model using the same connection string, and mapping the same entities, then added to my MVC project a reference to the new class library, and put at the top of both MyController and Prod class the next:
using MyClassLibrary;
Then I deleted the old model, now when I try to display the view, I get the following error:
Unable to load the specified metadata resource.
Any help please ?
When you move or rename the project the data context (.edmx) is in the metadata part of the Entity Framework connection string has to change
you can try have
connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;
instead of
connectionString="metadata=res://*/Models.MyModel.csdl|res://*/Models.MyModel.ssdl|res://*/Models.MyModel.msl;
or try deleting your context and recreating it then check the connection string it adds automatically.
You need to put your connectionstring in web.config in Mc4 web project
You need to Mention the datasource in the connection string.
If you have not used any other web.config file for views. Use you generic web.config file and upload a connection string with New datasource name , user and password.
I can't find how my connectionString syntax is wrong. Can anyone suggest a way to figure this out? I am having a difficulty using EF with my connection string. I am new to EF.
I am using Sybase Anywhere 12 database.
I'm using the Table-First ObjectContext with EDMX in a separate class library refenced by a web application.
I'm using a Ninject Module in my class library to bind my repositories.
I'm using a ODBC DataStore called "Test"
Other information EF 4.3.1.0, .NET 4, VS2010
My main web application web.config has the EF connection string copied to it as:
<connectionStrings>
<add name="Entities"connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=iAnywhere.Data.SQLAnywhere;provider connection string="UserID=aUser;Password=aPassword;DataSourceName=Test"" providerName="iAnywhere.Data.SQLAnywhere"/>
</connectionStrings>
When I initialize my Entity/ObjectContext in my Repository (see using statement below) it returns an error: "The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid."
using (var context = new Entities())
{
return {Linq to Entity here}
}
I turned on CLR exceptions on the debugger and found the code throws the error in the .NET Framework here:
EntityConnection.cs
effectiveConnectionOptions = new DbConnectionOptions(setting.ConnectionString, EntityConnectionStringBuilder.Synonyms, false);
edmx designer generated:
/// <summary>
/// Initializes a new Entities object using the connection string found in the 'Entities' section of the application configuration file.
/// </summary>
public Entities() : base("name=Entities", "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
I can see my connection string there, so it is having a difficult time parsing the connectionString. I have tried many different permutations of syntax and haven't found anything it accepts including:
Explicitly naming the assembly for entity files instead of a wildcard(e.g. metadata=res://MyDomain/MyEntities.csdl...)
Using Sybase friendly ODBC attributes such as UID instead of UserID, PWD instead of Password, and DBN instead of DataSourceName.
Thanks.
I got everything working and the only reason I can think of is that I deleted my ASP .NET 4.0 temp files. Also, I must add I changed my process from using an integration test to test this piece to using a unit test. I did not do unit tests first, because our build server does not have a database on it.
Once I was able to prove that it was working there, I decided to delete my temp files. After that, everything started working properly. So, some sort of cache issue was occurring in my application. I used the same connectionString that I mentioned above.
Actually, I used the domain name of the Metadata "metadata=res://MyDomain/MyEntitities.csdl" rather than */MyEntities.csdl. I don't plan on changing the domain any time soon. In fact, that is just what may have caused some of the issue, because I had changed the location, name, and namespace of MyEntities.Domain where the EF was.
I want to use Entity Framework without app.config file.
I want to define a string variable Connection String in my code and use that to connect to the database.
Please show me the way if it is possible.
You're not mentioning what approach you're using (database-first, model-first, code-first) - but basically, in the end, you need to define a string variable and assign it a valid EF connection string
string myConnectionString = "...(define a valid EF connection string here)......";
Example for database-first approach:
string myConnectionString = #"metadata=.\Model1.csdl|.\Model1.ssdl|.\Model1.msl;provider=System.Data.SqlClient;provider connection string="";data source=.;initial catalog=test;integrated security=True;multipleactiveresultsets=True;App=EntityFramework""";
and then use that to create your ObjectContext (database- and model-first) or DbContext (code-first)
using(ObjectContext ctx = new ObjectContext(myConnectionString))
{
// do your EF magic here.....
}
But quite honestly - I think this is a really bad idea since this makes it impossible for you to move your application to another machine - no one else can install and run this, since the connection string is hard-coded into your C# code..... the whole point of having config files is so that you can change / adapt things like connection strings so that they are not tied to a single machine/location but can be adapted to the particular needs of a given user / customer....