I have the following problem: My Program uses an .EDMX model generated from a SQL database with EF on the .NET framework.
When I work on the program at home from my desktop PC, I use Windows authentication. When I open the program at work, it is necessary to build a new .EDMX model with new PC name and standard SQL Server authentication.
How is it possible to change the connection string with a login window for example where I can chose user name, server name and DB name. MS Documentation is not a Help
Thanks for your help
First, you can define the helper to generate a runtime connection string for EDMX. you can find more options for your connection here
public static class Helper
{
public static string GenerateConnectionString(string server, string database, string username, string password)
{
return $"data source={server};initial catalog={database};persist security info=True;user id={username};password={password};" +
$"MultipleActiveResultSets=True;App=EntityFramework"";
}
}
Then add contractor for EDMX Model, for example, my Context model name is [banescoEntities]. "for find context you can type EMDXModelName and use F12 for go to DbContext". shown location on pic. But be careful if you rebuild Model Context, Mabe needs to rewrite code
public partial class banescoEntities : DbContext
{
// add this constractor
public banescoEntities(string connectionString)
: base(connectionString)
{
}
public banescoEntities()
: base("name=banescoEntities")
{
}
// other Context items
}
then create instance like :
internal class Program
{
static void Main(string[] args)
{
// generate ConnectionString runtime
var cs = Helper.GenerateConnectionString("172.31.4.24\\MSSQLSERVER2019", "banesco", "sa", "blablabal");
banescoEntities bsEntities = new banescoEntities(cs);
var products = bsEntities.Products.ToList();
}
}
Related
I'm trying to find a way to change the database name in my web.config and my context. No other info in my connection string changes but the database name.
public APIContext(string dbname = "MyFirstDB") : base("OriginalContext")
{
this.Database.Connection.ConnectionString = this.Database.Connection.ConnectionString.Replace("MyFirstDB", dbname);
}
The only way I can find to achieve this is to replace the name, but I can see few problems in the future, for example if I need to go back or need to point to another database. Using mysql.
Any help will be appreciated.
** EDIT **
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class APIContext : DbContext
{
public APIContext() : base("MyContext")
{
}
public void setDatabaseName(string name)
{
var currentdatabase = this.Database.Connection.Database;
this.Database.Connection.ConnectionString = this.Database.Connection.ConnectionString.Replace(currentdatabase, name);
}
Would this work if I were to call the "setDatabaseName(string name)" method before I call my context class?
I'm just confused on where I should be replacing the database name and how to do it.
Have you tried this?
public partial class MyModel : DbContext
{
public MyModel()
: base("name=MyModelDataContext") // <-- ConnString Name
{
}
}
And your connstring looks like this
<add name="MyModelDataContext" connectionString="data source=... initial catalog=YOURDB
This way you can change your db name any time.
this is actually how the code first from database wizard generates it
Ok, if you want to use more than one connstring you can do this
public class MyModel : DbContext
{
public MyModel ()
: base(ApplicationParameters.ConnectionStringName)
{
}
public MyModel (string connectionStringName)
: base(connectionStringName)
{
}
}
Then in your web.config you can set a list of connstrings and in your code you can call any of them with the second constructor.
I have this action method in MVC which retrieves data from table using a DbContext:
public ActionResult Index()
{
TwitterContext context = new TwitterContext();
List<TwitterUser> Users = context.User.ToList();
return View(Users);
}
It retrieves the values as expected:
But when I use the same code as a service, it retrieves nothing:
I am calling the service method from the client like this
public class TwitterController : Controller
{
// GET: Twitter
public ActionResult Index()
{
TwitterServiceReference.TwitterContractClient client = new TwitterServiceReference.TwitterContractClient("BasicHttpBinding_ITwitterContract");
List<TwitterServiceReference.TwitterUser> user = client.User().ToList();
return View(user);
}
}
I am using the same connection strings in both cases
<add name="TwitterContext"
connectionString="Integrated Security=true;initial Catalog=TwitterDatabase;server=MYNAME-PC\SQLEXPRESS"
providerName="System.Data.SqlClient"/>
I have all the data filled in the table:
Why is the data empty? How to solve this?
UPDATE:
After checking the SQL Server i see that a database is generated with the name
"TwitterService.TwitterContext , the database is autogenerated when i run the app, and the autogenerated tables data is empty, that is why i am getting empty data returned.
i think you forgot to copy your web.config connection string to that app.config.This might be the issue.
Edit:
i mean the project in which your DataContext class resides
The TwitterUser type you are using in MVC is in namespace Twitter.Models but the one you are using in WCF is in namespace TwitterServiceReference. Therefore, EF will treat them like different things. Your TwitterContext is also in different namespaces and as a consequence this is what is happening (from your comment):
I Just checked the SQL Server Management studio, i think the code created database named "TwitterService.TwitterContext" don't know how and with the same tables as DbContext class
And since it is a brand new database, it has no data and therefore in the WCF service you are not getting any records.
You can have different contexts and use the same database by specifying the same connection string as shown below:
public class TwitterContext : DbContext
{
public MovieDBContext()
: base("TwitterContext")
{
}
}
A Better Approach
Create a separate project and put all your DbContext related code in that project. Most people will refer to this as the Data Access Layer. Then use that project in both the MVC application and the WCF services. This way you will share the TwitterUser and other types in both, and possibly more, applications. You may use Repository Pattern to implement this layer.
But what if my MVC application needs additional info?
There will be cases where TwitterUser may not be sufficient for your MVC views and you may need additional properties. In that case, you can create a Model specifically for that view (some people call this view model but I stay away from that since that is a term used in MVVM and it is very different). The class can be designed like this:
public class TwitterUserModel
{
public TwitterUserModel(TwitterUser user)
{
this.TwitterUser = user;
}
public string AnotherPropertyNeededByView {get; set;}
public TwitterUser TwitterUser { get; set; }
}
Or you can use AutoMapper or similar mappers to map from TwitterUser to TwitterUserModel.
After some trials i got the success
i just added this code
public class TwitterContext : DbContext
{
//Added this Code with the connection string
public TwitterContext() : base(#"Integrated Security=true;server=MYNAME-PC\SQLEXPRESS;database=TwitterDatabase")
{
//Disable initializer
Database.SetInitializer<TwitterContext>(null);
}
public DbSet<TwitterUser> User { get; set; }
public DbSet<TwitterUserData> UserData { get; set; }
}
I first tried adding "TwitterContext" as base("TwitterContext") which is the name of my connection string and matches with my DbContext class name which did not work, so i directly added the connection string, the data is retrieved now and is preventing from generating new database.
I want to embed my entity datamodel to my class library that contains methods of database operations. (like MyEntityDatamodel.dll) Simply when i add my entity framework embedded class library to my windows forms application, i am able to use it's methods (insert update delete).
Currently i am able to running methods from dll but the problem is i must add EntityFramework.dll and EntityFramework.SqlServer.dll to my forms application as reference. Otherwise it doesn't work. I want to add only MyEntityDatamodel.dll.
Sample code of my entity datamodel class:
public class MyClass
{
public string classParameter { get; set; }
public void InsertMethod(MyClass parameter)
{
var dbContext = new MyEntities();
InsertOperations...
}
public void UpdateMethod(MyClass parameter)
{
var dbContext = new MyEntities();
UpdateOperations...
}
}
How I am using;
using MyClass;
MyClass myClass = new MyClass();
myClass.classParameter = "example";
myClass.InsertMethod(myClass);
Thanks in advance.
Two things to note...
First, directly to your question - you can't. You may try some sophisticated techniques like dynamically loading the assemblies your program needs, but this changes almost nothing except that you do not have them listed in your project references. They still need to be somewhere where the loader can find them. And more important they must always be deployed together with your app. Otherwise it won't work.
Second, DbContext is meant to be used as a Unit-of-Work design pattern, that is it needs to be disposed after the unit has finished whatever it was meant to do. Usualy, the using clause is a very good choice for this, so consider wrapping your code this way:
using (var dbContext = new MyEntities())
{
InsertOperations.../UpdateOperations...
}
After spending hours of on this, finally i found a solution. I am able to inject connection string to my dbcontext before my dbcontext object was created.
First, i changed my dbcontext's constructor method. I added string parameter for connection string instead reading from the web.config.
I changed this;
public partial class ExampleEntities : DbContext
{
public ExampleEntities()
: base("name=ExampleEntities")
{
}
}
To this;
public partial class ExampleEntities : DbContext
{
public ExampleEntities(string connStr) : base(connStr)
{
}
}
Then i added a method for Generating connection string to my code;
public static string CreateConnStr(string dataSource, string instanceName, string userName, string password)
{
string connectionString = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder
{
Metadata = "res://*/ExampleModel.csdl|res://*/ExampleModel.ssdl|res://*/ExampleModel.msl",
Provider = "System.Data.SqlClient",
ProviderConnectionString = new System.Data.SqlClient.SqlConnectionStringBuilder
{
InitialCatalog = instanceName,
DataSource = dataSource,
IntegratedSecurity = false,
UserID = userName,
Password = password,
}.ConnectionString
}.ConnectionString;
return connectionString;
}
Now i am simply use my dbcontext shown as below;
var dbContext = new ExampleEntities(CreateConnStr("localhost\\SQLEXPRESS","ExampleDataBase","UserName", "Password"));
Hope it helps.
P.s.: Sorry for bad grammar. :)
I have an application using MSSQLSERVER,when I deploy it to the customer, the server name could change, so I have to change the connection string of my xpo data model at run time,
this is the class generated with the XPO data model
public static class ConnectionHelper {
public const string ConnectionString = #"XpoProvider=MSSqlServer;data source=localhost;integrated security=SSPI;initial catalog=tkdoc";
public static void Connect(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
XpoDefault.DataLayer = XpoDefault.GetDataLayer(ConnectionString, autoCreateOption);
XpoDefault.Session = null;
}
public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption);
}
public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption, out IDisposable[] objectsToDisposeOnDisconnect) {
return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption, out objectsToDisposeOnDisconnect);
}
public static IDataLayer GetDataLayer(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
return XpoDefault.GetDataLayer(ConnectionString, autoCreateOption);
}
}
I'd like to change the ConnectionString in case the server or the user name or the password change
I suggest that you store the connection string in the application configuration file. This way, users can manually modify it, or you can provide them the special settings form for this purpose.
It is easy to read the connection string from the application configuration file. The code example can be found here on StackOverflow: Get connection string from App.config
How do I create connection string programmatically to MS SQL in Entity Framework 6?
I'm using c# and WPF and I was wondering if someone could show me how or link me to a resource that shows how to set up connection strings programmatically in EF 6. The MSDN article explains that you can http://msdn.microsoft.com/en-us/data/jj680699#moving but it doesn't go into creating actual connection strings.
So here is an EF6 example that works
App.Config
entityFramework codeConfigurationType="WPFwithEF.SqlConfiguration, WPFwithEF">
/entityFramework
context
public class ProductContext : DbContext
{
public ProductContext():base("Wpf")
{ }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
Configuration.cs
namespace WPFwithEF
{
public class SqlConfiguration : DbConfiguration
{
public SqlConfiguration()
{
SetProviderServices(SqlProviderServices.ProviderInvariantName,SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
}
but if the context base is "name=Wpf" then this set up does not work is there a way to make that work? And i'm looking for the latest EF6 not the old way to do it.
You can use the EntityConnectionStringBuilder as descriped here: How to: Build an EntityConnection Connection String
If you are specifically connecting to a MS Sql database, this should work:
private DbConnection CreateConnection(string connectionString)
{
return new SqlConnection(connectionString);
}
private string CreateConnectionString(string server, string databaseName, string userName, string password)
{
var builder = new SqlConnectionStringBuilder
{
DataSource = server, // server address
InitialCatalog = databaseName, // database name
IntegratedSecurity = false, // server auth(false)/win auth(true)
MultipleActiveResultSets = false, // activate/deactivate MARS
PersistSecurityInfo = true, // hide login credentials
UserID = userName, // user name
Password = password // password
};
return builder.ConnectionString;
}
how to use:
public void ConnectoToDbWithEf6()
{
using(var connection = CreateConnection(CreateConnectionString("server", "db", "you", "password")
{
using(var context = new YourContext(connection, true))
{
foreach(var someEntity in context.SomeEntitySet)
{
Console.WriteLine(someEntity.ToString());
}
}
}
}
see https://msdn.microsoft.com/en-Us/library/system.data.sqlclient.sqlconnectionstringbuilder%28v=vs.100%29.aspx
I previously used the DefaultConnection string found in the app.config ( or web.config) as example and just replaced the "connectionstring" on the DbContext, to the one i wanted.
The connectionstring looked something like :
Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-ShoppingList.Web-20150903103641.mdf;Initial Catalog=aspnet-ShoppingList.Web-20150903103641;Integrated Security=True
If i'm remembering correctly, you should replace the connectionstring in :
DbContext.Database.Connection.Connectionstring
PS. You can only use it this way if you are using Code-First. If you are using Model-First or Database-First you should use the EntityConnectionStringBuilder .
I investigated this question today. in my opinion the easiest solution is not mentioned above.
Why not use the SqlConnectionStringBuilder class? (using System.Data.SqlClient)
Here a simple example how to use it.
SqlConnectionStringBuilder sqlb = new SqlConnectionStringBuilder(getConnectionString(DATABASENAME);
using (SqlConnection connection = new SqlConnection(sqlb.ConnectionString))
...
)
// works for EF Core, should also work for EF6 (haven't tried this)
private static string getConnectionString(string databaseName)
{
return "Data Source=SQLSERVERNAME;Initial Catalog="+databaseName+";Integrated Security=True";
}
You could use the ProductivityTools.ConnectionString nuget package. It has 3 methods:
Creates connection string to server without database name
Creates connection string to server with the database name
Creates connection string for EntityFramework database context
Last method will be right for you and asssuming that your edmx is named Product after invocation
ConnectionStringHelper.ConnectionString.GetSqlEntityFrameworkConnectionString
("serverName", "databaseName", "Product");
Package will return:
metadata=res://*/Product.csdl|res://*/Product.ssdl| res://*/Product.msl;
provider=System.Data.SqlClient;provider connection string="Data Source=serverName;
Initial Catalog=databaseName;Integrated Security=True"