In my project i have to give a string input through a text field, and i have to fill a database table with these values. I should first check the values of a specific table column, and add the input string only if it is not there in the table already.
I tried to convert the table values to a string array, but it wasn,t possible.
If anyone have an idea about this, your reply will be really valuable.
Thankx in advance.
Since you say your strings in the database table must be unique, just put a unique index on that field and let the database handle the problem.
CREATE UNIQUE INDEX UIX_YourTableName_YourFieldName
ON dbo.YourTableName(YourFieldName)
Whenever you will try to insert another row with the same string, SQL Server (or any other decent RDBMS) will throw an exception and not insert the value. Problem solved.
If you need to handle the error on the front-end GUI already, you'll need to load the existing entries from your database, using whatever technology you're familiar with, e.g. in ADO.NET (C#, SQL Server) you could do something like:
public List<string> FindExistingValues()
{
List<string> results = new List<string>();
string getStringsCmd = "SELECT (YourFieldName) FROM dbo.YourTableName";
using(SqlConnection _con = new SqlConnection("your connection string here"))
using(SqlCommand _cmd = new SqlCommand(getStringsCmd, _con)
{
_con.Open();
using(SqlDataReader rdr = _con.ExecuteReader())
{
while(rdr.Read())
{
results.Add(rdr.GetString(0));
}
rdr.Close();
}
_con.Close();
}
return results;
}
You would get back a List<string> from that method and then you could check in your UI whether a given string already exists in the list:
List<string> existing = FindExistingValues();
if(!existing.Contains(yournewstring))
{
// store the new value to the database
}
Or third option: you could write a stored procedure that will handle the storing of your new string. Inside it, first check to see whether the string already exists in the database
IF NOT EXISTS(SELECT * FROM dbo.YourTableName WHERE YourFieldName = '(your new string)')
INSERT INTO dbo.YourTableName(YourFieldName) VALUES(your-new-string-here)
and if not, insert it - you'll just need to find a strategy how to deal with the cases where the new string being passed in did indeed already exist (ignore it, or report back an error of some sorts).
Lots of options - up to you which one works best in your scenario!
Related
I have a C# based api and I send queries to a mysql server. I wonder how can i read the id from a select to a table on C# Note that I am using MySql.Data.MySqlClient;
My code until the execute is this one below. But in this step I wonder how can I retrieve the desired id. I used ExecuteNotQuery but it seems it does not fit on what I need.
string connectionString = #"server=x.x.x.x;userid=xxxx;password=xxxxxx;database=testdatabase";
string getLastStoryIdQuery = "SELECT MAX(ID) FROM testdatabase.test";
MySqlCommand getLastTestIdCommand = new MySqlCommand(getLastStoryIdQuery, mySqlConnection);
int lastId = getLastStoryIdCommand.ExecuteNonQuery();
How can I retrieve the result as an Integer or in worst case as a string response? Thank you in advance. :)
int lastId = Convert.ToInt32(getLastStoryIdCommand.ExecuteScalar());
You can find the documentation on MySqlCommand here: https://dev.mysql.com/doc/dev/connector-net/8.0/html/T_MySql_Data_MySqlClient_MySqlCommand.htm
The method ExecuteNonQuery returns the number affected by the query, while ExecuteScalar returns the first column of the first row. You can also use ExecuteReader to get a datareader so that you can read a resultset the database produces.
In practice, I rarely use DbCommand/DbReader anymore and prefer to just use Dapper for database access in most cases where performance isn't absolutely critical. It simplifies parameter creation, and object filling which serves the vast majority of my use cases.
Dapper would look like this:
string connectionString = #"server=x.x.x.x;userid=xxxx;password=xxxxxx;database=testdatabase";
string getLastStoryIdQuery = "SELECT MAX(ID) FROM testdatabase.test";
int lastId;
using(var conn = new MySqlConnection(connectionString))
{
lastId=conn.Query<int>(getLastStoryIdQuery).First();
// you can also do the following in this instance, but you will use the
// above for results that return multiple rows or multiple columns
//lastId=conn.ExecuteScalar<int>(getLastStoryIdQuery);
// Here is how you use parameters:
// var something = conn.ExecuteScalar<int>("SELECT id FROM testdatabase.test WHERE id=#param",new {param = 10});
// This gets multiple columns and rows into a List<person> (assuming you have a person class with fname,lname,dob properties):
// var people = conn.Query<person>("SELECT fname,lname,dob FROM persons WHERE dob>#start", new {start=new DateTime(2000,1,1)}).ToList();
}
I've been tasked with creating a backup of the data in our "default schema" database dbo to the same database using a new schema called dbobackup.
I honestly do not understand what this means as far as a database goes. Apparently, it is like having a database backup inside the existing database. I guess there is some advantage to doing that.
Anyway, I can't seem to find anywhere online that will allow me to do this.
I have found a few posts on here about copying the schema without data, but I need the data too.
Backup SQL Schema Only?
How do I check to see if a schema exists, delete it if it does, and then create a schema that accepts data in the current database?
Once I have the new schema created, can I dump data in there with a simple command like this?
SELECT * INTO [dbobackup].Table1 FROM [dbo].Table1;
That line only backs up one table, though. If I need to do this to 245 tables for this particular customer, I'd need a script.
We have several customers, too, and their databases are not structured identically.
Could I do something along these lines?
I was thinking about creating a small console program to walk through the tables.
How would I modify something like the code below to do what I want?
public static void Backup(string sqlConnection)
{
using (var conn = new SqlConnection(sqlConnection))
{
conn.Open();
var tables = new List<String>();
var sqlSelectTables = "SELECT TableName FROM [dbo];";
using (var cmd = new SqlCommand(sqlSelectTables, conn))
{
using (var r = cmd.ExecuteReader())
{
while (r.Read())
{
var item = String.Format("{0}", r["TableName"]).Trim();
tables.Add(item);
}
}
}
var fmtSelectInto = "SELECT * INTO [dbobackup].{0} FROM [dbo].{0}; ";
using (var cmd = new SqlCommand(null, conn))
{
foreach (var item in tables)
{
cmd.CommandText = String.Format(fmtSelectInto, item);
cmd.ExecuteNonQuery();
}
}
}
}
SQL Server already has this built in. If you open SQL Server Management Studio and right click on the database you want to back up, then select all tasks then backup, you will get an option to back up your database into an existing database.
This is the important part and why you should use the built in functionality: You must copy the data from one DB to the other DB in the correct order or you'll get foreign key errors all over the place. If you have a lot of data tables with a lot of relationships, this will really be hard to nail down on your own. You could write code to make a complete graph of all of the dependencies and then figure out what order to copy the table data (which is essentially what SQL Server already does).
Additionally, there are third-party programs available to do this type of backup as well (see: Google).
This is sort of a "work in progress" approach I got started with that looks promising:
public static void CopyTable(
string databaseName, // i.e. Northwind
string tableName, // i.e. Employees
string schema1, // i.e. dbo
string schema2, // i.e. dboarchive
SqlConnection sqlConn)
{
var conn = new Microsoft.SqlServer.Management.Common.ServerConnection(sqlConn);
var server = new Microsoft.SqlServer.Management.Smo.Server(conn);
var db = new Microsoft.SqlServer.Management.Smo.Database(server, databaseName);
db.Tables.Refresh();
for (var itemId = 0; itemId < db.Tables.Count; itemId++)
{
var table = db.Tables.ItemById(itemId);
if (table.Name == tableName)
{
table.Schema = String.Format("{0}", DatabaseSchema.dboarchive);
table.Create();
}
}
}
The only issue I am currently running into is that my db variable always comes back with Tables.Count == 0.
If I get a chance to fix this, I will update.
For now, I've been told to remove this piece of code and check my code in.
I am trying to add some record to ACCESS file ,as you can see here :
string strconnection = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=AccessTemp.mdb";
private void InsertSellItems(List<TTMSModel> lstttms )
{
try
{
foreach (TTMSModel t in lstttms)
{
if (t.TypeMember == "حقیقی") t.TypeMember = "1";
else
{
t.TypeMember = "2";
}
OleDbConnection objconnection = new OleDbConnection(strconnection);
OleDbCommand objcommand = new OleDbCommand("INSERT INTO Foroush_Detail" +
"(KalaKhadamatName,KalaCode,BargashtType,Price,MaliatArzeshAfzoodeh,AvarezArzeshAfzoodeh,HCKharidarTypeCode,KharidarPostCode,KharidarPerCityCode,KharidarTell,KharidarAddress,KharidarName,KharidarLastNameSherkatName,KharidarEconomicNO,KharidarNationalCode,HCKharidarType1Code,CityCode,stateCode,IsSent,Sarjam)" +
"VALUES('فروش'," +"'0'"+",'0','"+t.PriceAmount+"','"+t.MayorAmount+"','"+t.TaxAmount+"','"+t.TypeMember+"','"+t.ZipCode+"','"+t.City+"','"+t.PhoneNumber+"','"+t.Address+"','"+t.Name+"','"+t.Name+"','"+t.EconomicNumber+"','"+t.IntNumber+"','2','"+t.City+"','"+t.Province+"','0','0')",
objconnection);
objconnection.Open();
objcommand.ExecuteNonQuery();
objconnection.Close();
}
}
catch (OleDbException a)
{
MessageBox.Show(a.Message);
}
}
I fetched the data from SQL server 2012.but after executing this query i got this error:
the field is too small to accept the amount of data you attempted to add access 2010.
The table structure is like this :
Best regards
For BargashtType column that is declared as Yes/No type, you are trying to insert فروش .Which is invalid, as the field will accept only 0 or 1 i.e. true or false.
It appears to me you are passing ever value in the query as a string, depite the fact some of the fields are numbers:
'"+t.City+"','"+t.Province+"'
Both of these values have a single quote around them, meaning they are strings, yet the two fields are Numbers.
That means you're leaving Access to do the conversion, you might want to try passing them as numeric values and see if that resolves the problem
I'm reading a CSV file a few times a day. It's about 300MB and each time I have to read it through, compare with existing data in the database, add new ones, hide old ones and update existing ones. There are also bunch of data that's not getting touch.
I have access to all files both old and new ones and I'd like to compare new one with the previous one and just update what's changed in the file. I have no idea what to do and I'm using C# to do all my work. The one thing that might be most problematic is that a row in the previous field might be in another location in the second feed even if it's not updated at all. I want to avoid that problem as well, if possible.
Any idea would help.
Use one of the existing CSV parsers
Parse each row to a mapped class object
Override Equals and GetHashCode for your object
Keep a List<T> or HashSet<T> in memory, At the first step initialize them with no contents.
On reading each line from the CSV file, check if the exist in your in-memory collection (List, HashSet)
If the object doesn't exists in your in-memory collection, add it to the collection and insert in database.
If the object exists in your in-memory collection then ignore it (Checking for it would be based on Equals and GetHashCode implementation and then it would be as simple as if(inMemoryCollection.Contains(currentRowObject))
I guess you have a windows service reading CSV files periodically from a file location. You can repeat the above process, every time you read a new CSV file. This way you will be able to maintain an in-memory collection of the previously inserted objects and ignore them, irrespective of their place in the CSV file.
If you have primary key, defined for your data then you can use Dictionary<T,T>, where you Key could be the unique field. This will help you in having more performance for comparison and you can ignore Equals and GetHashCode implementation.
As a backup to this process, your DB writing routine/stored procedure should be defined in a way that it would first check, if the record already exists in the table, in that case Update the table otherwise INSERT new record. This would be UPSERT.
Remember, if you end up maintaining an in-memory collection, then keep clearing it periodically, otherwise you could end up with out of memory exception.
Just curious, why do you have to compare the old file with the new file? Isn't the data from the old file in SQL server already? (When yous say database, you mean SQL server right? I'm assuming SQL server because you use C# .net)
My approach is simple:
Load new CSV file into a staging table
Use stored procs to insert, update, and set inactive files
public static void ProcessCSV(FileInfo file)
{
foreach (string line in ReturnLines(file))
{
//break the lines up and parse the values into parameters
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand command = conn.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[dbo].sp_InsertToStaging";
//some value from the string Line, you need to parse this from the string
command.Parameters.Add("#id", SqlDbType.BigInt).Value = line["id"];
command.Parameters.Add("#SomethingElse", SqlDbType.VarChar).Value = line["something_else"];
//execute
if (conn.State != ConnectionState.Open)
conn.Open();
try
{
command.ExecuteNonQuery();
}
catch (SqlException exc)
{
//throw or do something
}
}
}
}
public static IEnumerable<string> ReturnLines(FileInfo file)
{
using (FileStream stream = File.Open(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader reader = new StreamReader(stream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Now you write stored procs to insert, update, set inactive fields based on Ids. You'll know if a row is updated if Field_x(main_table) != Field_x(staging_table) for a particular Id, and so on.
Here's how you detect changes and updates between your main table and staging table.
/* SECTION: SET INACTIVE */
UPDATE main_table
SET IsActiveTag = 0
WHERE unique_identifier IN
(
SELECT a.unique_identifier
FROM main_table AS a INNER JOIN staging_table AS b
--inner join because you only want existing records
ON a.unique_identifier = b.unique_identifier
--detect any updates
WHERE a.field1 <> b.field2
OR a.field2 <> b.field2
OR a.field3 <> b.field3
--etc
)
/* SECTION: INSERT UPDATED AND NEW */
INSERT INTO main_table
SELECT *
FROM staging_table AS b
LEFT JOIN
(SELECT *
FROM main_table
--only get active records
WHERE IsActiveTag = 1) AS a
ON b.unique_identifier = a.unique_identifier
--select only records available in staging table
WHERE a.unique_identifier IS NULL
How big is the csv file?? if its small try the following
string [] File1Lines = File.ReadAllLines(pathOfFileA);
string [] File2Lines = File.ReadAllLines(pathOfFileB);
List<string> NewLines = new List<string>();
for (int lineNum = 0; lineNo < File1Lines.Length; lineNo++)
{
if(!String.IsNullOrEmpty(File1Lines[lineNum])
String.IsNullOrEmpty(File2Lines[lineNo]))
{
if(String.Compare(File1Lines[lineNo], File2Lines[lineNo]) != 0)
NewLines.Add(File2Lines[lineNo]) ;
}
else if (!String.IsNullOrEmpty(File1Lines[lineNo]))
{
}
else
{
NewLines.Add(File2Lines[lineNo]);
}
}
if (NewLines.Count > 0)
{
File.WriteAllLines(newfilepath, NewLines);
}
Is it possible to save a DataTable into SQL database in one cell of type binary for example and read it back again into a DataTable?
I would create, if possible, a xml field inside the sql database and save the datatable as xml
XML Support in Microsoft SQL Server 2005
and
C# and Vb.net example for XML data type tips in SQL Server 2005
should help you
another example took from here
protected bool LoadXml(SqlConnection cn, XmlDocument doc)
{
//Reading the xml from the database
string sql = #"SELECT Id, XmlField FROM TABLE_WITH_XML_FIELD WHERE Id = #Id";
SqlCommand cm = new SqlCommand(sql, cn);
cm.Parameters.Add(new SqlParameter("#Id",1));
using (SqlDataReader dr = cm.ExecuteReader())
{
if (dr.Read())
{
SqlXml MyXml= dr.GetSqlXml(dr.GetOrdinal("XmlField"));
doc.LoadXml( MyXml.Value);
return true;
}
else
{
return false;
}
}
}
why on earth would you want to?
If this is an operation you are going to do more than once, just save it out to a new sql table and read from the table into your DataTable later.
It just breaks normalization rules- the value in the cell is not atomic.
I break that rule myself all the time, but still, it's important to understand alternative approaches.
You could have a related table to store their answers instead of storing all their answer values in a single cell.
Regarding your comment below, you can still do it with a related table. Just use a three-column table: tableID, fieldID, value. Each tableID can have its own set of fieldIDs. The trade-off is with the value datatype- it needs to be a string, which means you don't get the advantages of date or numeric data type enforcement on your back end.