string connectionString =
"Data Source =|DataDirectory|\\user.sdf";
User context = new User(connectionString);
Userdetail newUser = new Userdetail();
newUser.Username = txtReg.Text;
newUser.Password = txtRegPassword1.Password;
try
{
context.Userdetail.InsertOnSubmit(newUser);
context.SubmitChanges();
}
catch (ChangeConflictException)
{
context.ChangeConflicts.ResolveAll(System.Data.Linq.RefreshMode.KeepChanges);
}
I want to add the new row of data (username, password) into the existing database but unfortunately it gets added temporarily only. As soon as the program is closed, the database is reverted to what it was.. Any help would be highly appreciated
Have you seen this:
Why isn't my SubmitChanges() working in LINQ-to-SQL?
Im assuming you're using Linq to Sql.
Linq to Entities would be: context.SaveChanges();
Related
I am using EF Code First approach for my model. I initialize my model with a SQLConnection like as below.
public myMODEL(DbConnection connection)
: base(connection, false)
{
}
I have a repository where I initialize the connection to the database.
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder
{
DataSource = serverName,
InitialCatalog = databaseName,
UserID = userId,
Password = passWord,
PersistSecurityInfo = true,
MultipleActiveResultSets = true
};
string providerString = sqlBuilder.ToString();
SqlConnection _entConn = new SqlConnection(providerString);
and the model every time I make a call as following.
using (myMODEL _mymodel = new myMODEL(_entConn))
{
}
I am using my repository as reference for a different project. After I initialize my repository in that project I store the same in application variable.
To give simple idea of my structure
An application variable =store> new object of repository [repository is
used as dll reference]
Whenever I make call to the same repository's public method => internally I initialize a new object of connection and a
new object of context
I am making queries as following
IQueryable<myset> mysetQuery = myMODEL.mysets.Where(m => ....);
var someList = mysetQuery.ToList();
Now though I am making changes in data in database, and am initializing connection and context everytime as I have said before, the EF query returns me previously stored values. I need the actual data from database. Anything I have missed.
Here is my code, it works when the database has the table "UserInformation"
public bool Save()
{
using (SqlConnection connection = new SqlConnection(ConnectionString)
{
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
try
{
using (var adapter = new UserInformationTableAdapter())
{
adapter.Connection = connection;
adapter.Transaction = transaction;
var table = new HelloDataSet.UserInformationDataTable();
HelloDataSet.UserInformationRow row = table.NewUserInformationRow();
row.UserName = userName;
row.Password = password;
row.Brithday = brithday;
table.Rows.Add(row);
adapter.Update(table);
transaction.Commit();
return true;
}
}
catch (Exception e)
{
transaction.Rollback();
return false;
}
finally
{
connection.Close();
}
}
}
However, when there is no table in the database, it will not create the "UserInformation" table in the database, it will jump to "catch" exception in line "adapter.Update(table);"
So my question is how can I create a new table in database if there is no "UserInformation" table in it. In addition, if the database already has the table "UserInformation" can I add a new column "Position" in that table?
Finally, I got the answer and want to share it out. First, I have to say that I put my question in a wrong way. What I really want is I have an application, and this application is connected with a database. However, I am allowed user to switch database. So, when the user switch to a new database I would like the application copy the entire database structure (not including the data) from the old one to the new one. Also, if I make some change (could be add a new column for one or more table, or add another new table) for the database in my application code, I would like every other database know the updates and make the same change by running my new application code.
So, here is my solution. I write a framework called "SchemaManager." It will create an additional table in each database, this table contains the version of the database. So, every time when I run my application the "SchemaManager" will check my hard code database version number with the database version number, if my hard code database version number is greater than the database version number, the "SchemaManager" will check the change and do the update for me.
I know my solution is not the best, but this is what I did. If anyone have anyother solution, please share with me and other people.
I'm having problems with updating a row in the Users table of my Access DB. Here is the code below:
private void SaveProfileInfo()
{
try
{
ChangeForeColorOfStatusMsg(Color.Black);
ChangeTextOfStatusMsg("Saving new profile information...");
const string cmd = #"UPDATE Users SET LastName=#LastName,FirstName=#FirstName,MiddleName=#MiddleName,Add_Num=#Add_Num,Add_Street=#Add_Street,Add_Brgy=#Add_Brgy,Add_City=#Add_City,MobileNumber=#MobileNumber,Gender=#Gender WHERE ID=#ID;";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbCmd.Parameters.AddWithValue("#LastName", txtLastName.Text);
dbCmd.Parameters.AddWithValue("#FirstName", txtFirstName.Text);
dbCmd.Parameters.AddWithValue("#MiddleName", txtMiddleName.Text);
dbCmd.Parameters.AddWithValue("#Add_Num", txtUnitNum.Text);
dbCmd.Parameters.AddWithValue("#Add_Street", txtStreet.Text);
dbCmd.Parameters.AddWithValue("#Add_Brgy", GetBrgySelectedItem());
dbCmd.Parameters.AddWithValue("#Add_City", GetCitySelectedItem());
dbCmd.Parameters.AddWithValue("#MobileNumber", txtMobileNumber.Text);
dbCmd.Parameters.AddWithValue("#Gender", GetGenderSelectedItem());
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeForeColorOfStatusMsg(Color.MediumSeaGreen);
ChangeTextOfStatusMsg("All changes have been saved! This window will close itself after two seconds.");
Thread.Sleep(2000);
CloseForm();
}
catch (Exception)
{
ChangeForeColorOfStatusMsg(Color.Crimson);
ChangeTextOfStatusMsg("Something went wrong while we were connecting to our database. Please try again later.");
hasFinishedEditting = false;
}
}
This method will be done on a separate thread, when the user updates his profile information.
UserLoggedIn is actually a field of a User class (a class that defines a row in my table), which stores all the info of the user who's currently logged in.
When I run this, it does not produce any exceptions or errors. But when I check my table, the values are not updated.
I copy-pasted these codes from the registration form (which works) that I made with this system, and modified it into an UPDATE cmd than an INSERT cmd.
I also made Change Username and Password Forms that use the same cmd as shown below:
public void ChangePass()
{
try
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("Changing password...");
const string cmd = "update Users set Pass=#Pass where ID=#ID";
var dbConn = new OleDbConnection(cs);
var dbCmd = new OleDbCommand(cmd, dbConn);
dbCmd.Parameters.AddWithValue("#Pass", txtNewPass.Text);
dbCmd.Parameters.AddWithValue("#ID", UserLoggedIn.ID);
dbConn.Open();
dbCmd.ExecuteNonQuery();
dbConn.Close();
ChangeTextOfMsg("Password successfully changed!");
}
catch (Exception)
{
ChangeForeColorOfMsg(Color.Silver);
ChangeTextOfMsg("A problem occurred. Please try again later.");
}
}
And these codes work for me. So I'm really confused right now as to why this update cmd for the profile information isn't working... Is there something I'm not seeing here?
OleDb cannot recognize parameters by their name. It follows a strictly positional order when sending them to your database for updates. In your code above the first parameter is the #ID but this parameter is used last in your query. Thus everything is messed up.
You just need to move the add of the #ID parameter as last in the collection
As a side note, you should be very careful with AddWithValue. It is an handy shortcut, but it has a dark side that could result in wrong queries.
Take a look at
Can we stop using AddWithValue already?
I'm doing Code First development with Entity Framework 6, using Database Migrations, and I'm using a new database that is populated with sample seed data. I'd like to be able to initialize my database with that seed data any time I change the model.
The catch is this: I don't have database create permissions; because of this, I can't just utilize DropCreateDatabaseIfModelChanges.
Is there a way that I can programmatically drop all of my tables, or am I stuck manually deleting them from the database each time?
Ultimately, I didn't need to delete the tables, just the data they contained.
I ended up solving this by simply truncating a list of tables at the beginning of my Seed method, based on this answer.
protected override void Seed(MyContext context)
{
var listOfTables = new List<string> { "Table1", "Table2", "Table3" };
foreach (var tableName in listOfTables)
{
context.Database.ExecuteSqlCommand("TRUNCATE TABLE [" + tableName + "]");
}
context.SaveChanges();
// seed data below
}
If you're not using automatic migrations, but code based migrations, you can back all the way down to the first version using the follow command:
Update-Database –TargetMigration: 0
This will follow the Down path on all of your migrations until you have a clean database. Then you can execute:
Update-Database
This will bring everything back up to date. This solution assumes you've properly maintained your Down path and seeded your data with Migrations. I do this for my integration tests to ensure I start with the data in an expected state.
My suggestion is to use the local DB or another DB you have full permission on (Azure is nice, and free if you have a MSDN account). Then migrate that final DB schema over once it's set in stone and ready for production.
That being said, this might be helpful, but I've never tried it before.
If you dont have permission access to the database, it may be better to address that issue.
Anyway:
public bool TruncateTable(string connectionString, string schema, string tableName) {
var statement = "TRUNCATE TABLE [{0}].[{1}] ;";
statement = string.Format(statement, schema, tableName);
return ExecuteSqlStatement(connectionString, statement);
}
public bool DeleteAllEntriesTable(string connectionString, string schema, string tableName) {
var statement = "DELETE FROM [{0}].[{1}] ;";
statement = string.Format(statement, schema, tableName);
return ExecuteSqlStatement(connectionString, statement);
}
public bool ExecuteSqlStatement(string connectionString, string statement, bool suppressErrors = false) {
int rowsAffected;
using (var sqlConnection = new SqlConnection(connectionString)) {
using (var sqlCommand = new SqlCommand(statement, sqlConnection)) {
try {
sqlConnection.Open();
rowsAffected = sqlCommand.ExecuteNonQuery(); // potential use
}
catch (Exception ex) {
if (!suppressErrors) {
// YOUR ERROR HANDLER HERE
}
return false;
}
}
}
return true;
I have a server that hosts 50 databases with identical schemas, and I want to start using Entity Framework in our next version.
I don't need a new connection for each of those databases. The privileges of the one connection can talk to all of the 50 databases, and for data management and speed (this is a WebAPI application) I don't want to instantiate a new EF context every time I talk to each of the databases if I don't have to, unless of course if this occurs each time a request comes to the server then no big deal.
All I really need is the ability to change the USE [databasename] command, which I assume eventually gets sent to the server from EF.
Is there a way to accomplish this in code? Does EF maintain a read/write property in the Context that refers to the database name that could be changed on the fly before calling SaveChanges(), etc.??
Thank you!!!
bob
Don't Work hard, work smart !!!!
MYContext localhostContext = new MYContext();
MYContext LiveContext = new MYContext();
//If your databases in different servers
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("localhost", "Live");
//If your databases have different Names
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("DBName-Localhost", "DBName-Live");
the structure for databases should be the same ;)
You can take a look at:
SO question about passing existing SQL Connection to
EntityFramework Context
and at this article describing how to
change database on existing connection.
Please let me know if any additional help is needed.
Edited
Updated 2nd link to point to SqlConnection.ChangeDatabase method.
So eventually code would look similarly to the following:
MetadataWorkspace workspace = new MetadataWorkspace(
new string[] { "res://*/" },
new Assembly[] { Assembly.GetExecutingAssembly() });
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
using (EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection))
using (NorthwindEntities context = new NorthwindEntities(entityConnection))
{
// do whatever on default database
foreach (var product in context.Products)
{
Console.WriteLine(product.ProductName);
}
// switch database
sqlConnection.ChangeDatabase("Northwind");
Console.WriteLine("Database: {0}", connection.Database);
}
It is very simple
I had
public WMSEntities() : base("name=WMSEntities") //WMSEntities is conection string name in web.config also the name of EntityFramework
{
}
already in autogenerated Model.Context.cs of edmx folder.
To connect to multiple database in runtime, I created another constructor that takes connection string as parameter like below in same file Model.Context.cs
public WMSEntities(string connStringName)
: base("name=" + connStringName)
{
}
Now, I added other connection string in Web.Config for example
<add name="WMSEntities31" connectionString="data source=TESTDBSERVER_NAME;initial catalog=TESTDB;userid=TestUser;password=TestUserPW/>
<add name="WMSEntities" connectionString="data source=TESTDBSERVER_NAME12;initial catalog=TESTDB12;userid=TestUser12;password=TestUserPW12/>
Then, when connecting to database I call below method passing connectionString name as parameter
public static List<v_POVendor> GetPOVendorList(string connectionStringName)
{
using (WMSEntities db = new WMSEntities(connectionStringName))
{
vendorList = db.v_POVendor.ToList();
}
}
Here's my solution for just changing the database name. Simply pull the string from the web or app.config file, modify it, and then instantiate:
string yourConnection = ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString.Replace("MyDatabase", yourDatabaseName);
dcon = new MyEntities(yourConnection);
I have implemented this in my current project in which we have a common security database and different database for every client in the project. So our security database has a table that contain connection string for every other database. We just pass client id and get the connection string of the client database..
For this add two EDMX one for the common database and other for common schema databases. When user login or what might be your scenario to choose database go to common databse and get the connection string and create object of the needed database. Here is Code sample any, if any quer let me know..
You can keep connection string regarding every other database in a table in a a common database shared by all the other database.
EntityInstance_ReviewEntities.GetContext(GetConnectionString(ClientId));
private string GetConnectionString(int TenantId)
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
ISecurityRepository objSecurity = new SecurityRepository();
string tenantConnectionString = objSecurity.GetClientConnectionString(TenantId);
entityBuilder.ProviderConnectionString = tenantConnectionString;
entityBuilder.Provider = "System.Data.SqlClient";
entityBuilder.Metadata = #"res://*/ClientEntity.YourEntity.csdl|res://*/ClientEntity.ADBClientEntity.ssdl|res://*/ClientEntity.YourEntity.msl";
return entityBuilder.ToString();
}
EntityConnection.ChangeDatabase method is not supported, but SqlConnection.ChangeDatabase works fine.
So you have to use SqlConnection in entity framework database's constructor:
using MvcMyDefaultDatabase.Models;
using System.Data.Metadata.Edm;
using System.Data.SqlClient;
using System.Data.EntityClient;
using System.Configuration;
using System.Reflection;
public ActionResult List(string Schema)
{
SqlConnection sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetExecutingAssembly() });
EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection);
sqlConnection.Open();
sqlConnection.ChangeDatabase(Schema);
Models.MyEntities db = new MyEntities(entityConnection);
List<MyTableRecords> MyTableRecordsList = db.MyTableRecords.ToList();
return View(MyTableRecordsList);
}
With this code you can read the tables with the same format (same table name and same fields) of several schema passing the database name in the "Schema" string.
For SQL Server, if you want to change only the database, not a connection, try:
public class XXXXDbContext : DbContext
{
public string databaseName
{
set
{
Database.GetDbConnection().Open();
Database.GetDbConnection().ChangeDatabase(value);
}
}
}