I got some data inputed by the user that should be added to a Database File (.sdf). I've choose Sql Server CE because this application is quite small, and i didn't saw need to work with a service based database.
Well any way.
Here goes the code:
public class SqlActions
{
string conStr = String.Format("Data Source = " + new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\basedados.sdf");
public SqlCeConnection SQLCEConnect()
{
SqlCeConnection Connection = new SqlCeConnection(conStr);
Connection.Open();
return Connection;
}
public Boolean AdicionarAuditorio(string Nome, int Capacidade)
{
string Query = "INSERT INTO auditorios (nome, capacidade) VALUES (#Nome, #Capacidade)";
using (var SQLCmd = new SqlCeCommand(Query, SQLCEConnect()))
{
SQLCmd.Parameters.AddWithValue("#Nome", Nome);
SQLCmd.Parameters.AddWithValue("#Capacidade", Capacidade);
if (SQLCmd.ExecuteNonQuery() == 1)
{
return true;
} else {
return false;
}
}
}
}
I use the AdicionarAuditorio(string Nome, int Capacidade) function to Insert the data. running ExecuteNonQuery() which is supposed to return the number of affected rows after he as run the query.
So it should return 1 if the query as successful, right?
In the end he returns 1, but if I browser the table data, the data that the query should add isn't there.
So whats wrong here?
NOTE. If your thinking that the
problem is the connection: I can't see
why is the problem once i got some
Select statements that use that
connection function SQLCEConnect()
and they all work pretty well.
Thanks in advance.
Are you sure you are looking at the right file? When you build your app in VS, it copies the SDF file as content to the target folder, so the database in your project will not reflect any updates. Your code is picking up the the file location there.
This is btw not a good practice, because once deployed, the program folders are not writable to your app (could this be the problem - did you already deploy?). Instead, the database file should reside in your appdata folder.
Is it possible that you make the call to AdicionarAuditorio in a TransactionScope without calling transactionScope.Complete()?
Related
I'm connected to an external SQL server in my "Data Connections" (in the "Server Explorer" view). I can right click my SQL source and click "New Query" to quickly look up data with SQL statements.
I would like to use LINQ instead and I think the "C# Interactive" window would be a good and quick way to do this. My problem is that I don't know how to access my 'open' data connection. The name of the database or tables are not recognized.
Yes, you can right click on your main project in Solution Explorer and click Initialize Interacive with Project. This will build you projects and import all the dlls into the interactive window for you. Then you can start scratching!
For example, using Entity Framework you will need to stand up your DbContext. Enter something like...
> var context = new My.Namespace.MyDataContext("blah blah blah");
Where I have written the "blah blah blah" you need to add your connection string. The interactive console does not know about your .config files so you need to provide the connection string.
Note: To be able to do this make sure you have the nameOrConnectionString constructor override on your data context.
Now that you have the context it is as simple as normally querying the context...
> context.Users.Where(u => u.IsActive).Select(u => u).ToList()
Important
Take note that I have left the semicolon (;) off the end of the query. This is important as it tells the console to output the value of the query/command/line of code. Nothing will happen if you leave this off.
I got this to work by creating a class library that opens a connection to an EF data model, importing the DLL into the C# interactive window, and executing Linq statements against the data model.
First, create the class library, add the EF data model, and modify your DbContext (entities) class to use the constructor that takes a connection string. You need to do this to use this library from the c# interactive window, because if you don't, the interactive window will be looking for an app.config file with the connection string.
public partial class YourDBEntities : DbContext
{
public YourDBEntities(string connectionString)
: base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
....
}
If your class library, add a class with a static method for getting a data context:
public class AccessorClass
{
public static YourDBEntities GetDataContext()
{
return new YourDBEntities("metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=\";data source=xxxxxxx;initial catalog=xxxxxxx;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework\";");
}
}
Compile the class library, and then import the DLL into your interactive window, and query away:
> #r "C:\Path...\bin\Debug\YourClassLibrary.dll"
> using YourClassLibrary;
> using (var ctx = AccessorClass.GetDataContext())
. {
. Console.Write(ctx.Orders.Where(c => c.ProjectID == 309).Count().ToString());
. }
The solution I am proposing may not be exactly what you are looking for, but I think it will help you figuring out what you need. One way I have done sth similar is by creating a DA library and using that in C# Interactive Window. Below is the sample:
I would have a class library project, MyProject.MyDA:
namespace MyDa
{
public class CustomerDa
{
public DataTable LoadData(string sqlCommandText = "")
{
//do your try catch finally and all the good stuff
var connString = #"Data Source=ServerName;Initial Catalog=AdventureWorks2014;Integrated Security=SSPI;";
var conn = new SqlConnection(connString);
SqlDataReader dataReader;
//you could accept the command text as a parameter
string sql = "select top 10 * FROM [AdventureWorks2014].[HumanResources].[Department]";
var result = new DataTable("Department");
conn.Open();
SqlCommand command = new SqlCommand(sql, conn);
dataReader = command.ExecuteReader();
result.Load(dataReader);
dataReader.Close();
command.Dispose();
conn.Close();
//instead of a datatable, return your object
return result;
}
}
}
Build your DA project, now in C# Interactive, you would do sth like:
> #r "D:\blah\Blah\MyDa\bin\Debug\MyDa.dll"
> using MyDa;
> var a = new CustomerDa();
> var r = a.LoadData();
> r.Rows[0]
DataRow { HasErrors=false, ItemArray=object[4] { 1, "Engineering", "Research and Development", [4/30/2008 12:00:00 AM] }, RowError="", RowState=Unchanged, Table=[] }
> r.Rows.Count //you can do all the good LINQ stuff now on the result
10
You can do it this way, but I feel this flow requires more work and ceremony than I would like and is still imperfect. Anyways, that's one way to accomplish what you are looking for. I would also recommend using LinqPad if you prefer to query using LINQ.
This Sould work !
SELECT
DB_NAME(dbid) as DBName,
COUNT(dbid) as NoOfConnections,
loginame as LoginName
FROM
sys.sysprocesses
WHERE
dbid > 0
GROUP BY
dbid, loginame
You can check this link find number of open connection on database
I have a program which is supposed to open, edit, create and save access databases. For saving I copy an empty database with just the tables (just to avoid going through the hassle of creating every table and column etc) and try to fill it with values via the TableAdapterManager.UpdateAll method.
string _TemplateConnectString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};";
_connection = new OleDbConnection(string.Format(_TemplateConnectString, dlg.FileName));
_connection.Open();
DataSet1TableAdapters.TableAdapterManager tam=new TableAdapterManager();
tam.Connection = _connection;
try
{
tam.UpdateAll(dataset);
}
catch (System.Exception ex)
{
MessageBox.Show("Update failed");
}
It finishes with no exceptions but the values don't get inserted into the new database.
Also as far as I know the UpdateAll method only updates modified row so if I open some db and it inserts it's rows, it will not take them into account even though there are not in the database that I am trying to fill.
I have also tried filling the database with the ADODB and ADOX extensions but all the solutions I found with those was a lot of hardcoding and no regards for hierarchy, keys, etc.
Is there a way to force insert everything in the new database?
Is your template database in the Visual Studio project directory? It might have something to do with Visual Studio copying the database to the bin/debug or bin/release folder...
Try to use the right Data source database name, here an
example with an excel file:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\ExcelFile.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
A clumsy solution but it works. I iterate the tables of the dataset and save the via an sql string generator like this:
void SaveTable(DataTable dt)
{
string[] inserts;
try
{
inserts = SqlHelper.GenerateInserts(dt, null, null, null);
foreach (string s in inserts)
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = s;
cmd.Connection = _connection;
int n = cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
SaveOk = false;
}
}
I found the SqlHelper somewhere on this site, but completely lost where, unforunately. So here is the pastebin with it https://pastebin.com/iCMVuYyu
A program written in C# Oracle client that proved to have "Connection leak" which it is not closing all database connections and so after some time it can no longer connect to the database as there are too many open connections.
I wrote the following helper function (quite expansive):
private static int tryFindConnCount(){
var connstk = new Stack<Oracle.ManagedDataAccess.Client.OracleConnection>();
try
{
for (var i = 0; i < 10000; ++i)
{
var conn = new Oracle.ManagedDataAccess.Client.OracleConnection(
myDatabaseConnection);
conn.Open();
connstk.Push(conn);
}
}
catch(Exception e)
{
foreach (var conn in connstk)
{
conn.Close();
}
}
return connstk.Count;
}
Here is the code in a test case that uses the above:
var co = tryFindConnCount();
CodeThatMayLeakConnection();
var cn = tryFindConnCount();
Assert.That(cn, Is.EqaulTo(co));
It helped me identify at least one case that have connection leak.
The problem of tryFindConnCount is that it should never be used in production. And I think there should be some way to obtain the same value much cheaper.
How can I do this in the code so I can monitor this value in production?
Trying to find places where connections where not closed is a difficult task.
If you leave the program and forget to close the connection the last sql which was executed is stored in column SQL_ID in v$session (gv$session for RAC). You can search v$session for idle/dead sessions. You can then use v$sql to find the SQL text which may tell you more about what was done last. By this you may get a hint where to search in your code.
select a.sid, a.username, a.program, a.machine, a.sql_id, b.sql_fulltext
from v$session a, v$sql b
where b.sql_id(+) = a.sql_id
and a.username is not null -- filter system processes, maybe filter more stuff
;
You can query Oracle DB on "gv$session" view to get the info that you need. With a query on this view you can cyclically monitor the DB every 10-15 minutes for a count of connections from this program.
Example query below :
select count(*)
from gv$session
where machine = 'XXXXX'
and username = 'YYYYY'
and program = 'ZZZZZ';
You only need values that uniquely identify those connections like for example machine from which the connections originate.
Also the query is very light and doesn't add performance overhead.
How can I with "code" create a new .mdf/.sdf database?
I've tried this:
http://support.microsoft.com/kb/307283
All it does is fail on the ConnectionString. Since I have no connection to a file that exists before I create it, how can I only connect to the SQL Express Server just to create a mdf/sdf database?
I want to be able to just connect to the server and create the file, from there it probably will be easier to create the tables and such.
Any suggestions?
public static void CreateSqlDatabase(string filename)
{
string databaseName = System.IO.Path.GetFileNameWithoutExtension(filename);
using (var connection = new System.Data.SqlClient.SqlConnection(
"Data Source=.\\sqlexpress;Initial Catalog=tempdb; Integrated Security=true;User Instance=True;"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
String.Format("CREATE DATABASE {0} ON PRIMARY (NAME={0}, FILENAME='{1}')", databaseName, filename);
command.ExecuteNonQuery();
command.CommandText =
String.Format("EXEC sp_detach_db '{0}', 'true'", databaseName);
command.ExecuteNonQuery();
}
}
}
Change Catalog=tempdb to Catalog=master, its good worked
Sample use:
var filename = System.IO.Path.Combine("D:\\", "testdb.mdf");
if (!System.IO.File.Exists(filename))
{
CreateSqlDatabase(filename);
}
Regarding .sdf files (SQL Server CE), you can use the SqlCeEngine class to create a new database, as described in this MSDN article.
Create .sdf database
using System.Data.SqlServerCe;
using System.IO;
string folderPath="D:\\Compact_DB"
string connectionString;
string fileName =folderPath+"\\School.sdf";
string password = "12345";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", fileName, password);
SqlCeEngine obj_ceEngine = new SqlCeEngine(connectionString);
obj_ceEngine.CreateDatabase();
Make sure you have a valid connection string.
The database/catalog that you need must be set to a valid database, usually this can be the "master" which is always available and since you will be using master to create a database.
If you need to create a database from scratch programmatically i normal go into the SQL Server Management Studio and create it through the gui in a first step. But instead of clicking on the OK button in the bottom right, i click on the Script button in the top toolbar. This will give me a complete sql script for creating the database i'd like to have. Then i can alter the script and change the parts i'd like dynamically.
I suppose the problem is in the ConnectionString. It should point to the valid instance of the master db (as in the article you refer to). Make sure it is correct, and it should work.
Use a connectionString with InitialCatalog = master. Since only master has default access to create a database.
I have an application that saves and opens data (which is saved as SQL CE database file). Every time the project gets saved, a new .sdf file is generated with table structure defined by my code and I do not need to run any validation against it.
My concern is when user import (open) the .sdf file in a OpenFileDialog, there will be chance user may select a database file generated from a different application (i.e. having a different table schema). I would need to validate the importing database table schema or the application may crash if the wrong database file is opened and processed.
I do not need to compare schema between files. All I need is to check if the database file contain a certain table structure or table names (which I think should be sufficient for my purpose). What is the easiest way to do this?
[EDIT]
I used the following method to validate the database file, which works. I use a string array to checked against a SqlCeDataReader (which stores the Table name). It works but I wonder if there's an even easier way - is there a build in method in .NET to use?
using (SqlCeConnection conn = new SqlCeConnection(validateConnStr))
{
using (SqlCeCommand cmd = new SqlCeCommand(#"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES", conn))
{
try
{
conn.Open();
SqlCeDataReader rdr = cmd.ExecuteReader();
string[] tableArr = { "FirstTable", "SecondTable" };
int ta = 0;
while (rdr.Read())
{
if (rdr.GetString(0) != tableArr[ta])
{
isValidDbFile = false;
}
else
{
isValidDbFile = true;
}
ta++;
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
}
}
Open the database (make sure to have error handling for this, as the user can point to any file).
run: SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'MyTable'
If this returns data, your table is there.