Entity Framework: multiple DB having the same schema - sql-server

I have just created an ASP.NET MVC 4 & WebAPI project. After that I have added .edmx data source to project.
I have multiple databases with the same schema. Dynamically I want to replace connection string using default constructor provided in EF.
But in Model1.Designer.cs, every time I get error like "Member with same signature already declared".
I'm unable to solve this problem.

Yes, it works! All you need to change is the connection string.
And I have just tested it in order to satisfy my own curiosity.
Here are the steps that I took:
Take an existing database and create a model for it.
Create a new empty database.
In SQL Management Studio right click the first database -> Tasks -> Export Data. Export all it's data to the newly created database.
Remove some records from the second database.
Write this code:
TMS_MiscEntities db = new TMS_MiscEntities();
TMS_MiscEntities dbCopy = new TMS_MiscEntities();
dbCopy.Database.Connection.ConnectionString = db.Database.Connection.ConnectionString.Replace("initial catalog=TMS_Misc", "initial catalog=TMS_Misc_new");
Response.Write(string.Format("DB 1 records: {0}<br/>", db.ZipCodes.Count()));
Response.Write(string.Format("DB 2 records: {0}<br/>", dbCopy.ZipCodes.Count()));
Check results:
DB 1 records: 869164
DB 2 records: 868709
Conclude that it works :)
This is how my connection string looks:
<add name="TMS_MiscEntities" connectionString="metadata=res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl;provider=System.Data.SqlClient;provider connection string="data source=ws2008;initial catalog=TMS_Misc;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />

I'm using Entity Framework 6.1.3. I have added a constructor to my DbContext that takes a string parameter. This string can be the name of the connection stored in your App.config or a full connection string. Something like this:
public partial class MyDBContext : DbContext
{
public MyDBContext(string connectionString)
: base(connectionString)
{
}
// DbSets, OnModelCreating, etc
}
In my case, I manage a multi-tenant application and I use a ContextFactory to build the proper connection string and return my initialized context.
public class ContextFactory
{
public MyDbContext GetContext()
{
string connectionString;
// do some stuff here
return new MyDbContext(connectionString);
}
}

Related

How to add-migrations for auto-generated databases?

I have an application which contains to context classes. One is master context class and second is sub context class. When I run the application for the first time the master database gets generated. And whenever I create a new user, a database related to that user gets generated using sub context class. For example, if I create 10 users then 10 databases will get generated using sub context class like sub_db_userId.
The problem is enabling migrations in this complex structure. I know some people would say it's not appropriate to create new database use foreign key relation but I have to work on requirements.
I found this thread very helpful in finding how to enable-migrations for separate context classes but in my scenario, it does not apply changes to existing databases because of database name is associated with user ids. Rather applying changes to existing child databases it creates new database without user id like this sub_db_. How can I solve this issue?
The way I am creating the new database for every user is given below.
My context classes:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false) {}
}
public class SubDbContext : DbContext
{
public DbSet<Country> Countries { get; set; }
public DbSet<City> Cities { get; set; }
public SubDbContext() : base("SubDatabaseConnection")
{
}
public SubDbContext(string connectionString) : base(connectionString)
{
Database.SetInitializer<SubDbContext>(new
CreateDatabaseIfNotExists<SubDbContext>());
}
}
Connection strings:
<add name="DefaultConnection"
connectionString="Data Source=.\SQLExpress;Initial Catalog=master_db;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="SubDatabaseConnection"
connectionString="Data Source=.\SQLExpress;Initial Catalog={0};Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
I am using {0} for formatting purposes. How can I enable migrations and apply changes to existing databases?
Modifications: I am linking tables to database in Register action like this:
SubDbContext newContext = new SubDbContext(string.Format(userDatabase, "sub_db_" + userId));
newContext.Countries.FirstOrDefault();
newContext.Cities.FirstOrDefault();
Your DbContext for all your sub-databases is SubDbContext. So you must enable migration based on one of them. then put this code as Configuration class:
internal sealed class Configuration : DbMigrationsConfiguration<SubDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
}
and put this code into the SubDbContext constructor:
Database.SetInitializer<SubDbContext>(new MigrateDatabaseToLatestVersion<SubDbContext, Configuration>());
it means, every database when found a new manual added Migration,
then try to migrate it.
and also you can use this approache too:
write this code in the Application_Start:
var context = new SubDbContext("your generated connection string");
var initializeMigrations = new MigrateDatabaseToLatestVersion<SubDbContext, Configuration>();
initializeMigrations.InitializeDatabase(context);
I hope you find it helpful.

Change connection EF at runtime in WPF app

I have a WPF app that I'd like to change the connection string programmatically when the app loads. I use the Database-First approach for EF.
I spent a lot of time implementing various solutions found online including stack overflow and can't seem to get it to work.
The most common way seems to be to modify the Entity partial class. When I do this I get the following error at runtime:
Additional information: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
I got the same error implementing various other ways as well. If someone could please help me implement a way to change the connection string at runtime I'd greatly appreciate it.
My current implementation is taken from this example solution:
Changing Databases at Run-time using Entity Framework
Implementation:
App.config containts the connection string and name
Partial class added with same name as Entity class:
Imports System.Data.Entity
Imports System.Data.EntityClient
Imports System.Data.SqlClient
Partial Public Class MyEntityName
Inherits DbContext
Public Sub New(ByVal connString As String)
MyBase.New(connString)
End Sub
End Class
In my Application.xaml code file I set a global string variable by calling a method that builds the EntityConnectionStringBuilder. This global string variable is then passed into an entity constructor.
Imports System.Reflection
Imports DevExpress.Xpf.Core
Imports System.Data.EntityClient
Class Application
Public Sub New()
entityConnStr = BuildConnectionString("[MyDataSource]", "[MyDatabase]")
End Sub
Private Function BuildConnectionString(ByVal DataSource As String, ByVal Database As String) As String
' Build the connection string from the provided datasource and database
Dim connString As String = "data source=" & DataSource & ";initial catalog=" & Database & ";persist security info=True;user id=[user];password=[password];trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework""
' Build the MetaData... feel free to copy/paste it from the connection string in the config file.
Dim esb As New EntityConnectionStringBuilder()
esb.Metadata = "res://*/DB.[MyEntityName].csdl|res://*/DB.[MyEntityName].ssdl|res://*/DB.[MyEntityName].msl"
esb.Provider = "System.Data.SqlClient"
esb.ProviderConnectionString = connString
' Generate the full string and return it
Return esb.ToString()
End Function
Usage:
Using context = New MyEntity("entityConnStr")
Public connection variable string:
Public entityConnStr As String
I think you should remove the quotes when you pass the connection string to the constructor. You want to use the variable contents, not the variable name.
Use this:
Using context = New MyEntity(entityConnStr)
Instead of this:
Using context = New MyEntity("entityConnStr")

How do I access the elmah database from code?

VS2013 update 4, MVC5, elmah.mvc (same as elmah), VB/C#
The following code is part of the standard MVC template to get started and it is part of setting up our database connection from within code to access an SQL database:
Public Class ApplicationDbContext
Inherits IdentityDbContext(Of ApplicationUser)
Public Sub New()
MyBase.New("DefaultConnection", throwIfV1Schema:=False)
Me.Configuration.LazyLoadingEnabled = True
End Sub
Public Shared Function Create() As ApplicationDbContext
Return New ApplicationDbContext()
End Function
We also need the following or something similar in web.config:
<configuration>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=mypc\SQLEXPRESS;Initial Catalog=mydb.DefaultContext;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="ElmahConnection" connectionString="Data Source=mypc\SQLEXPRESS;Initial Catalog=mydb.elmah;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
I added the elmah connection string as it is relevant to my question.
Then in each location where needed, the following definition is added and we can access the database tables using db.< tablename>...:
Private db As New ApplicationDbContext
I want to write some methods to work with and on the elmah data table but it is a different context than ApplicationContext. I don't quite understand what I would write to setup a connection to the elmah table since I didn't really set that up, it came in the dll for elmah.
While keeping error records makes sense, during development I wanted to clear the Elmah log. While probably trivial for most, it was a good exercise to figure it out. I was so used to code first, I forgot EF also does database first.
In VS2013 update 4 the following Wizard made this task pretty easy.
1) Project > Add New Item > Data > ADO.NET Entity Data Model
2) Give the model a name (With great creativity I used 'elmah') > Click Add
3) This is where it gets pretty cool. I'm not sure when it was added but the EF framework now includes a new choice called Code First From Database. Click on that.
4) Select the elmah connection string
Note: There is an option to save connection settings in web.config. That simply creates a duplicate connection string. Leave it checked or don't, but using the existing string is fine. I didn't select the option and web.config was left untouched. However, not using that option means the connection string name will have to be updated in the context definition > Click Next
5) Click on Tables to load the Elmah table, leave the defaults as is > Click Finish
The wizard creates 2 files and places them in the project. One is named by the data table name which is ELMAH_Error; this is the model. The other is a parital class that sets up the context. If the save connection option was selected then web.config will be modified to add the new connection string.
Note: I combined the 2 Classes into a single file for convenience (may require adding some Using or Imports) and the Public Sub New() is where the connection string name must be updated if the existing connection string is used as shown below.
Partial Public Class elmah
Inherits DbContext
Public Sub New()
MyBase.New("name=ElmahConnection")
End Sub
Public Overridable Property ELMAH_Error As DbSet(Of ELMAH_Error)
Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
End Sub
End Class
6) With all that automatically done (except for the connection string name if required), all that is required is to write the desired code. I wanted to empty the elmah log from time to time and used the following:
Public Class ErrorController
Inherits Controller
Private db1 As New elmah
Function DeleteElmahRecords() As ActionResult
Dim elmahTable = db1.ELMAH_Error.ToList()
db1.ELMAH_Error.RemoveRange(elmahTable)
db1.SaveChanges()
Return RedirectToAction("ErrorTesting")
End Function
…
End Class
Obviously I have a method called ErrorTesting that the function returns to and I access this method from a link on that same page.
Hope this is useful for someone. It's kind of the only way I can give back considering the awesome guru help I often get from this site.

SQL Server Session Serialization in ASP.Net MVC

I am new to ASP.Net MVC . Any help is greatly appreciated in resolving my problem.
I am using a LINQToSQL db in my MVC application. For one of the auto generated partial class (Example MyClass assume for table MyClass) , I created another Partial class as MyClass and added DataAnnotations Like following...
namespcae NP
{
[MetadaType(typeof(myData))]
[Serializable()]
public partial class MyClass
{
}
public myData
{
[Required]
public string ID { get ; set ;}
// Other properties are listed here
}
}
In my controller class example MyHomeController
I have a code as follows:
List<MyClass> list = new List<MyClass>();
list = dbContext.StoredProcedure(null).ToList<MyClass>()
session["data"] = list.
above code works fine if I use inProc session state. But if I use SQLServer mode then I get error as
"Unable to serialize the session state. In 'StateServer' and
'SQLServer' mode, ASP.NET will serialize the session state objects,
and as a result non-serializable objects or MarshalByRef objects are
not permitted. The same restriction applies if similar serialization
is done by the custom session state store in 'Custom' mode. "
Can anyone tell me what I am doing wrong here..?. I can see the data is getting populated in ASPState database tables. By application throws error as follows.
Just mark as Serializable all classes whose instances you want to store in Session.
Finally I was able to resolve the issue.
Solution:
Add the below statement before querying the database. In my case I was calling LinqToSQl context( dbContext).
dbContext.ObjectTrackingEnabled = false;
Sample Code:
List empList = new List();
dbContext.ObjectTrackingEnabled = false;
empList = dbContext.SomeStoredProcedure().ToList()
Session["employee"] = empList.

MVC: Connect class to results of database function/stored procedure

How can I execute a SQL function in MVC?
I am trying to link the results of a table returning function to a class I defined. I have set up the connection string and created the database context with public DbSet<Classname> variable{get; set;} how can i link this to the results of a function
Are you using Entity Framework? Here is an article you can read:
http://rationalgeek.com/blog/function-imports/

Resources