In a project, I have a local database, (I am using the datagrid to view the data), but the problem is that when I insert into database using the insertion query, the insertion is not lasting, i.e. when I rerun the application, the database is not changed and the changes are not reflected in the database view (view table data in Visual Studio).
The insertion query is:
string dbCon = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\MyDatabase.sdf";
SqlCeConnection dbconnection = new SqlCeConnection("datasource=" + dbCon);
dbconnection.Open();
String Insert = "insert into MainTable(LineID,Date,Connection_Type) Values('5','5/8/2012','commercial')";
SqlCeCommand cmd = new SqlCeCommand(Insert, dbconnection);
//// Execute the command
cmd.ExecuteNonQuery();
dbconnection.Close();
Now when this code runs, the datagrid is updated, but the changes are not permanent. What is it that I am doing wrong?
I am using Visual Studio 2010 Ultimate and Windows 7
In what folder is your application running? If it is in the Program Files tree you likely do not have write permissions to the sdf file (especially on Windows 7 unless you have turned off UAC or are elevating your app prior to execution).
Even if that is not your short term issue I would recommend finding a different place for the sdf file, such as one of the AppData locations. Expecting to be able to write to your install location is not a guaruntee and depends on how and where your app is deployed.
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\MyDatabase.sdf" is the path to your application folder. Depending on installation options your file may not be installed there. Use a connection string of "DataSource=|DataDirectory|\\MyDatabase.sdf;..." as described here.
Even if your data is actually stored there, depending on user permissions the user may not be able to write to that directory. Also, when the user uninstalls or updates your app, his data will be deleted. People don't like that. You should copy the data to a user-writable folder; the earlier link shows how to do that as well.
If you have a Visual Studio project with a database a part of your project, it will probably have the "Copy to Output Directory" property set to "Copy". That means each time you run in the debugger you get a brand-new database copied from your source project, overwriting whatever was there before. Any changes will be in this temporary output folder, not in your original source data. When you debug the app again, the temporary copy is deleted. Further explanation in this answer.
Related
I have a C# application that creates an installer with a Setup project in Visual Studio. It all works fine except for the SQLite database that I am trying to include.
What I have done:
Added the database file from my solution to the Application Folder of the Setup project.
Stored the connection string in my code where I use it to create the connection.
private const string conString = "DATASOURCE = HCATDatabase.sqlite; VERSION = 3;";
SQLiteConnection dbConnection = new SQLiteConnection(conString);`
Rebuilt the Setup project and the Solution.
Installed the program from the created installation.
What happened when I fired the installed application:
The database gives errors like "No such table", while the database in my solution does have these tables.
The application shows data that is not in the database from my solution.
I compared the database files with DB Browser (the one from my project that I included in my Setup project and the one in the installed program's file) and they are identical.
So somehow the program uses a different (third) database file.
How can I find out where the program gets this file from and how can I change it to use the proper file?
UPDATE: I have found thanks to #Roger Lipscombe that the program uses a database file in C:\Users\User\AppData\Local\VirtualStore\Program Files (x86)\ProgramCompany\MyProgram.
UPDATE 2: I deleted the folders (that were pretty old) in the above directory and that fixed everything, the program now references the correct database. I would love it if someone could explain all of this.
I've got this code in my Winforms app to create a table in an existing database, (which I created by following what is written here):
private void CreateTables()
{
string connStr = #"Data Source=
(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|
\AYttFM.mdf;Integrated Security=True";
using (var connection = new
System.Data.SqlClient.SqlConnection(connStr))
{
try
{
connection.Open();
using (var command = connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE [dbo].[AssignmentHistory] ");
sb.Append("(");
sb.Append("[Id] INT NOT NULL PRIMARY KEY, ");
sb.Append("[WeekOfAssignment] DATE NOT NULL,");
sb.Append("[TalkType] INT NOT NULL,");
sb.Append("[StudentID_FK] INT NOT NULL, ");
sb.Append("[AssistantID_FK] INT NOT NULL, ");
sb.Append("[CounselPoint] INT NOT NULL");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
It runs without complaint, but no table is created. Refreshing both the Data Connection and its Tables folder in Server Explorer in Visual Studio Community 2015 show no tables.
Am I missing something in the code above?
Note: I broke the connStr over several lines above for formatting purposes; in the actual code, connStr is all on one line.
I'm also not able to connect to the .mdf file via LINQPad, using the "Default LINQ to SQL" and SQL Server Provider and navigating to the .mdf file in my project (C:\AYttFMApp\AYttFMScheduler\AYttFMScheduler\AYttFM.mdf). It tells me there is a network error:
I get that whether I use the default Server ".\SQLEXPRESS" or whether I set it to my machine name (which is the only entry beneath "Servers" in Visual Studio's Server Explorer).
UPDATE
I rebooted my laptop, but it didn't help. Server Explorer's Data Connections show nothing, even after I refresh, and trying to add one, with my machine name as the Server Name (after all, that is what it says the Server is there in Server Explorer) and selecting the .mdf file gives me the same error when testing the connection as LINQPad does.
UPDATE 2
Curiouser and curiouser: Now when I run my app, when it gets to the Create Table code, I get an exception msg that says the AssignmentHistory table has already been created. Yet if I look at Server Explorer, although the database itself is back again, its Tables folder is still empty. How can the table both be there and not be there?
I'm still wondering if the properties set on the .mdf file are wrong; as I wrote in a comment below, the properties are all the defaults: "Copy to Output Directory" is set to "Copy Always" and "Build Action" is set to "Content" Should either of these be changed?
If the code does not throw any exceptions on line command.ExecuteNonQuery() then the query did finish and the table should be there. It could be that you are just looking at the wrong database as you are using the LocalDb. If the project has included the .MDF as a file and it is marked to always be copied to the destination directory then what is happening is that VS is always looking at the unaltered copy and the Execute statement always completes during debugging because the unaltered copy is always replacing the copy that is used at run time.
The DataDirectory specifies a placeholder for a location that is usually assigned in the application startup. You can get the full path to the actual .mdf file being used like so:
var fullFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), "AYttFM.mdf");
I have appended the name of your .mdf LocalDb to the end of the path.
You can add this line of code and get the path of the file and then open this instance up with the Visual Studio table designer.
Alternatively you can change the connection string and hard code it to a specific instance of your .mdf file that is guaranteed not to change when you do a build on the project.
Edit based on your latest edits
"Object reference not set to an instance of an object" is what I get
after running the line you provided.
I made the assumption you were setting the DataDirectory location manually, my apologies. If you do not set the variable manually then for a windows application the default location is the .exe path. So the code should be updated to the following:
var fullFilePath = System.IO.Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString(), "AYttFM.mdf");
This will probably resolve to something like .\yourProjectFolder\debug\bin\AYttFM.mdf.
The properties are all the defaults: "Copy to Output Directory" is set
to "Copy Always" and "Build Action" is set to "Content"
So that affirms what I wrote earlier. Every time you do a build it will copy the .mdf to your executable directory and basically refreshes the database to its original state. Note that you can do multiple runs from visual studio which means that if everything has already been compiled and nothing has changed a new .exe and content will not be re-copied over the existing one. This is why you are sometimes seeing an exception and other times you are not, it just depends on if the .mdf was overwritten or not.
Should either of these be changed?
This should be OK but it depends on if it's ok to start with a clean slate every time. That is really up to you, here are the available options you have:
From MSDN - File Properties
Copy to Output Directory Property
This property specifies the conditions under which the selected source
file will be copied to the output directory. Select Do not copy if the
file is never to be copied to the output directory. Select Copy always
if the file is always to be copied to the output directory. Select
Copy if newer if the file is to be copied only when it is newer than
an existing file of the same name in the output directory.
If you want to open the .mdf file all you have to do is double click on it in the VS project, it should open up in Server Explorer -> Data Connections. There is no reason to open the output file (the copy of the .mdf) in your designer, I would only edit the file in your project as with your current setup this is the master file that will overwrite the output file every time.
I have no experience with LINQPad so I can't say if this application can attach to a LocalDb instance or not. Here is a post about how to possibly do this from a previous SO question.
Open SQL Server configuration manager and check if your server is running. If it's not - then run it:
I am writing a program in Visual C# 2015. I have created a local database from within the IDE and everything seems to work fine after building and running locally. However, after publishing the application and installing on another machine I get an argument exception error at attachdbfilename. I have included the database as a content file. The ClickOnce does copy the database to a folder under APPS in my Appdata folder. I have installed SQL Local DB edition on the target machine. The database name is ConnectionsDatabase.mdf.
These are definitions in my Settings.Designer.cs file.
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\ConnectionSet" +
"tings.mdf;Integrated Security=True; User Instance=True")]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\ConnectionsDa" +
"tabase.mdf;Integrated Security=True; User Instance=True")]
Not sure if they should both be there for just 1 database.
This is what I use for connection string within the appropriate classes.
using
(SqlConnection con = new SqlConnection(Store_Switcher.Properties.Settings.Default.ConnectionsDatabaseConnectionString))
I am willing to share any and all project files that are needed. Keep in mind this is a small application that will be installed on several different machines. Please help!! This is driving me crazy!
AttachDbFilename=|DataDirectory|\ConnectionSet" + "tings.mdf
should be
AttachDbFilename=|DataDirectory|\ConnectionData" + "base.mdf
in your designer file. or vice versa. you have a disconnect in file names.
EDIT:
You mean "invalid value for key"? The problem sounds like whatever path you are using for the database on the target system doesn't match your development machine.
You even say "The ClickOnce does copy the database to a folder under APPS in my Appdata folder. " So maybe on your dev box you have c:\myapp\App_Data\ConnectionData.mdf and on target it is c:\myapp\App_data\APPS\ConnectionData.mdf after it gets deployed.This won't work. Get rid of the APPS, or change your code so the deployment folder is the same as on your dev box. This is a path issue.
I have a local DB that I have in an application. When I install it on another machine I get the error
Unable to update database.. .mdf is read only.
I was able to get around it by editing my permissions on the .mdf and log file themselves. I did some research and noticed that I may want to install the database to a shared folder. However, I am not sure how to do that and the answers I did come across did not make a whole lot of sense to be.
//My connection string
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|AssetDatabase.mdf;Integrated Security=True");
Any guidance would be greatly appreciated. I am learning.
Just go to the program files and find the folder of the installed program.
Just right click the .mdf file in the folder and click PROPERTIES.
In PROPERTIES TAB -> SECURITY -> you'll see Group or Usernames.
In that select the User to which u want to give Access to the file.
If for that user the PERMISSION is not set to FULL CONTROL.
TO CHANGE PERMISSIONS -> CLICK EDIT.
Now the Group or Username box will open.
In that Select The User -> Select FULL CONTROL in Permission Box.
Now follow the steps for the log file too. IF Needed.
OR
Just install your application in different folder other than ProgramFile(x86)
The MDF file would be readonly either because the readonly file attribute flag is set, in which case you have to unset it, or another program has the MDF file locked as readonly. Are you running a version of SQL server that is using that file?
I've never seen a connection to the MDF file directly, usually it's done via the server, and the server will manage all the IO for the MDF file.
E.g. a typical connection string for SQL Server:
Database=<dbname>;Server=<servername>;MultipleActiveResultSets=True;Connection Timeout=10;User Id=<username>;Password=<password>;
Additional links:
1) Failed to update .mdf database because the database is read-only (Windows application)
2) Failed to update database because it is read-only
3) Failed to update database "*.mdf" because read only EntityFramework
4) http://www.codeproject.com/Questions/183758/Failed-to-update-mdf-database-because-the-database
First stop the SQLEXPRESS service from local-Services menu and then try to move and connect the database again by attaching database option in SQLEXPRESS. it should work. it works for me. :)
I solved the same problem as follows:
While creating "Setup", I manually added my database files database.mdf and database_log.ldf into the Application Folder file. But after adding these files, make sure that the ReadOnly option in the Properties section is False.
Also "connectionString" I use:
connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\database.mdf;Integrated Security=True;Connect Timeout=30"
just remove the .mdf file location to c:\ or desktop or anywhere but not in
%program file directory
if your database file on the C volume,
try to move the .mfd file to D volume
This is probably a stupid mistake of me.. but I can't seem to understand it.
I've created a new, empty C# Windows Forms application.
I added a Database (Based on a dataset) and have the file stored in my solution explorer.
I've added a table Test with column Name.
I add a record using new SqlCeCommand("insert into Test values('Name')", new SqlCeConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)).ExecuteNonQuery();
However, I've even tried retrieving the same data and it all works perfectly.
But when I stop my project, and rebuild it.. all data is gone again?
Is there a way to fix this, or will this fix itself when I'll start using this project for what it is intended (Without the 500 rebuilds a day?)
Your database file is listed in the project with this property
Copy to destination directory = Copy Always
If this is true then every time you restart the project a fresh (empty) copy of the database file is copied from the project directory to the output directory (BIN\DEBUG or BIN\RELEASE) overwriting the database file used in the previous run. You could avoid this changing the property to Copy Never or Copy if newer
The answer given by steve keeps copying the database over the existing one, which results in removing all data.
I've managed to fix this by putting "Copy Always" on, then in the explorer move the database to a different location and add it to the project. This way the database will never be overwritten and can be used in the program!
(However, this will probably raise a issue if/when I publish the project to another computer)