Windows Forms save to dataset but not table [duplicate] - database

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.

It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.

Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

Related

Xamarin Forms - How do i use a Premade Local Database? [Solved] [duplicate]

I have started using the Xamarin plugin for Visual Studio to create an Android app.
I have a local SQL database, and I want to call it to display data. I don't see how I can do this. Is it possible?
After thinking this was a trivial thing to do, I was proven wrong when I tried setup a quick test project. This post will contain a full tutorial on setting up a DB for an Android App in Xamarin that will come in handy as a reference for future Xamarin users.
At a glance:
Add Sqlite.cs to your project.
Add your database file as an Asset.
Set your database file to build as an AndroidAsset.
Manually copy the database file out of your apk to another directory.
Open a database connetion using Sqlite.SqliteConnection.
Operate on the database using Sqlite.
Setting up a local database for a Xamarin Android project
1. Add Sqlite.cs to your project.
Start by going to this repository and downloading Sqlite.cs; this provides the Sqlite API that you can use to run queries against your db. Add the file to your project as a source file.
2. Add DB as asset.
Next, get your DB and copy it into the Assets directory of your Android project and then import it into your project so that it appears beneath the Assets folder within your solution:
I'm using the Chinook_Sqlite.sqlite database sample renamed to db.sqlite from this site throughout this example.
3. Set DB to build as AndroidAsset.
Right click on the DB file and set it to build action AndroidAsset. This will ensure that it is included into the assets directory of the APK.
4. Manually copy DB out of your APK.
As the DB is included as an Asset (packaged within the APK) you will need to extract it out.
You can do this with the following code:
string dbName = "db.sqlite";
string dbPath = Path.Combine (Android.OS.Environment.ExternalStorageDirectory.ToString (), dbName);
// Check if your DB has already been extracted.
if (!File.Exists(dbPath))
{
using (BinaryReader br = new BinaryReader(Android.App.Application.Context.Assets.Open(dbName)))
{
using (BinaryWriter bw = new BinaryWriter(new FileStream(dbPath, FileMode.Create)))
{
byte[] buffer = new byte[2048];
int len = 0;
while ((len = br.Read(buffer, 0, buffer.Length)) > 0)
{
bw.Write (buffer, 0, len);
}
}
}
}
This extracts the DB as a binary file from the APK and places it into the system external storage path. Realistically the DB can go wherever you want, I've just chosen to stick it here.
I also read that Android has a databases folder that will store databases directly; I couldn't get it to work so I've just ran with this method of using an existing DB.
5. Open DB Connection.
Now open a connection to the DB through the Sqlite.SqliteConnection class:
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
// Do stuff here...
}
6. Operate on DB.
Lastly, as Sqlite.net is an ORM, you can operate on the database using your own data types:
public class Album
{
[PrimaryKey, AutoIncrement]
public int AlbumId { get; set; }
public string Title { get; set; }
public int ArtistId { get; set; }
}
// Other code...
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
var cmd = new SQLite.SQLiteCommand (conn);
cmd.CommandText = "select * from Album";
var r = cmd.ExecuteQuery<Album> ();
Console.Write (r);
}
Summary
And that's how to add an existing Sqlite database to your Xamarin solution for Android! For more information check out the examples included with the Sqlite.net library, its unit tests and the examples in the Xamarin documentation.
Here is the one that I'm using and it's working
install the Sqlite plugin
create interface to access different platforms services
create a model for the table
implement the interface that you created earlier on all of the
platform you want to use
use the plugin to create, get, insert, etc on your table
for more detailed information check this

Can't create sqlite db on production machine

I have a program that works correctly on my computer in Debug mode.
When my program start he create a Sqlite data base file if not exists.
This is ok on my computer.
I create a setup version for production version. The program setup is ok.
But when I start the program (.exe) my db file is not created.
This is the connection string I used :
static string dbDirectopry = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
static string dbName = "MySqliteDb.db";
static string Connexion = Path.Combine(dbDirectopry, #"MySociety\MyApplication\" + dbName);
Hi thanks for your help,
this is the code that create db.
public static void CreateDb(string path)
{
SqLiteHelper sqlite = new SqLiteHelper(path);
try
{
User.CreateTable();
}
catch (Exception e)
{
throw e;
}
}
Normaly if the file doesn't exists he is automaticaly created.
If I try my application in Debug mode with Visual Studio my db is created and I can write into.
But when I deploy my application it doesn't work anymore.
My problem is is there any special directory (for windows) to create de db file?

Batch create extranet users in Composite C1

I am in the process of building a website that in near future shall replace an existing web-site. The existing web-site contains aprox. 300 users which I need to "import" to the extranet-module (which I have bought) in composite.
Is there a way to batch create users to the extranet module?
Yes, you can import your existing user database. You can either do this by writing a script and have that execute on your web site or by directly manipulating the underlying SQL table / XML file (depending on what you use to store Composite C1 data). You can also build a provider that links your existing user database with Composite C1 Extranet.
Importing users programmatically: For a script approach please see methods like AddNewUser described on http://docs.composite.net/Packages/Community/Extranet/CompositeCommunityExtranetDeveloperGuide/Using-Extranet-Facade-Methods
You would write this script as web service, aspx page or similar which executes on the Composite C1 website.
If you are running the Extranet in a default setup expect the providerName to be "Default".
Manipulating the physical data store directly: This depends on what data store you are running on. I suggest you add the groups you want and a test user to help you recognize data when you look at the underlying XML files / SQL tables.
If you are running on XML (default) you should focus on the files named Composite.Community.Extranet.DefaultProvider.DataTypes.DefaultProvider*.xml located in the folder ~/App_Data/Composite/DataStores. There are 3 sush files, one for groups, one for users and one for the relation between users and groups.
If you are running on SQL Server you should focus on the 3 tables named Composite.Community.Extranet.DefaultProvider.DataTypes.DefaultProvider*
In both cases you would need to add new entries to the User table/xml file and matching group relations to the GroupUser table/xml file. When you add a user you provide a unique ID and this ID you reuse to register the user in GroupUser.
When you have made your changes you can force Composite C1 to reload by using the Tools | Restart Server command in the C1 Console. If you make a backup of files/tables before you make changes you can easily revert by restoring the backup (in case you need to start over).
Writing a user/group provider: If your user data is in an external store and you would like to keep it there you could also make a bridge between this existing user store and the Composite C1 Extranet by creating a custom provider. If this is relevant see http://docs.composite.net/Packages/Community/Extranet/CompositeCommunityExtranetDeveloperGuide/Writing-Custom-Extranet-Providers
Thank you. It now works. I imported the users programmatically. I opened the composite solution in visual studio and added a aspx page. Here is the code behind.
using System;
using System.Collections.Generic;
using System.IO;
using Composite.Community.Extranet;
using Composite.Community.Extranet.Data;
public partial class ImportUsers : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string path = Server.MapPath("UsersToImport.csv");
StreamReader _streamReader = new StreamReader(path);
IList<Guid> userIds = new List<Guid>();
string line;
while ((line = _streamReader.ReadLine()) != null)
{
string[] fields = line.Split(',');
IExtranetUser extranetUser = new ExtranetUser();
extranetUser.Name = fields[0];
extranetUser.UserName = fields[1];
extranetUser.Email = fields[2];
extranetUser.IsApproved = true;
IExtranetUser addedUser = ExtranetFacade.AddNewUser("Default", extranetUser);
userIds.Add(addedUser.Id);
ExtranetFacade.SetUsersForGroup("Default", new Guid("bc728100-e28e-4135-a14c-bead6e0b9b00"), userIds);
Response.Write(string.Format("User: {0} added at {1}", addedUser.UserName, addedUser.CreationDate));
}
}
}

Create a SQLite database with Monotouch - permission denied

I am trying to create a Sqlite database using Monotouch 3.0.3.4. Everything works fine on the iPhone simulator, but I get the following error on the test iPhone:
DataLayer.CreateDatabase Exception: System.UnauthorizedAccessException: Access to the path "/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3" is denied.
Here is the code I am using:
// creates database and tables if they do not exist.
public void CreateDatabase ()
{
string sql = string.Empty;
string dbFileName = "myDatabase.db3";
try {
if (!File.Exists (dbFileName)) {
// create database
SqliteConnection.CreateFile (dbFileName); //This is where the error occurs
Console.WriteLine ("CreateDatabase: Database created.");
...
}
catch (Exception ex) {
Console.WriteLine ("CreateDatabase Exception: " + ex.ToString ());
}
...
I have also tried specifing the personal folder, but that has no effect. What do I need to do to make sure permissions are correct?
Thanks!
Monotouch 3.0.3.4
That's likely MonoDevelop 3.0.3.4. See About MonoDevelop to get the MonoTouch version.
"/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3"
On devices the applications are signed, so their content can't change (without breaking the signature). As such you're not allowed to change things in the .app directory.
You should create (or copy) the database in the Documents directory and then open the database as read-write.
See the linked article for more details.

Setting PathAnnotation on SSIS path from code

I have been trying lately to create SSIS packages from .NET code rather than using drag and drop in Visual Studio. As part of the package documentation, I would like to be able to annotate data flow paths.
The code below - copied from MSDN - establishes a path between two SSIS data flow components. By adding
path.Name = "My name";
new Application().SaveToSqlServer(package, null, "localhost", "myUser", "myPassword");
I can set the name of the path to whatever I like and then save the package in my local SQL Server. When I open the package in Visual Studio 2008, however, the name of the path can only be seen under path properties.
In Visual Studio, there is another path property, PathAnnotation, with the value AsNeeded and additional possibilities SourceName, PathName, Never. Changing the value to PathName gives me what I want: The path name appears next to the path in the data flow tab in Visual Studio.
My question is: Is it possible to set the value of the PathAnnotation property from code?
using System;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
namespace Microsoft.SqlServer.Dts.Samples
{
class Program
{
static void Main(string[] args)
{
Package package = new Package();
Executable e = package.Executables.Add("STOCK:PipelineTask");
TaskHost thMainPipe = e as TaskHost;
MainPipe dataFlowTask = thMainPipe.InnerObject as MainPipe;
// Create the source component.
IDTSComponentMetaData100 source =
dataFlowTask.ComponentMetaDataCollection.New();
source.ComponentClassID = "DTSAdapter.OleDbSource";
CManagedComponentWrapper srcDesignTime = source.Instantiate();
srcDesignTime.ProvideComponentProperties();
// Create the destination component.
IDTSComponentMetaData100 destination =
dataFlowTask.ComponentMetaDataCollection.New();
destination.ComponentClassID = "DTSAdapter.OleDbDestination";
CManagedComponentWrapper destDesignTime = destination.Instantiate();
destDesignTime.ProvideComponentProperties();
// Create the path.
IDTSPath100 path = dataFlowTask.PathCollection.New();
path.AttachPathAndPropagateNotifications(source.OutputCollection[0],
destination.InputCollection[0]);
}
}
I succeeded in getting an answer in a different forum. Please see
http://social.msdn.microsoft.com/Forums/en-US/sqlintegrationservices/thread/23e6a43f-911f-44da-8e69-cd9e53d7e5ed

Resources