I just want to to know if some data exists in the database.
Normaly I use SqlDataReader, take a loop SqlDataReader put variable in array or list,
and in Business layer again loop over the array or List and compare with the X data to see if it is in the list or array.
SqlDataReader readerOne = comm_SelectOne.ExecuteReader();
while (readerOne.Read())
{
...
}
I think this is not efficient, there are two loops (in Data Access layer to Collect and in Business layer to compare)
Is there another way to do this with a DataSet?
No there is'nt 'In' or 'Contains' function in DataSet because DataSet itself is a container of DataTable and data is saved in DataRow associated with any particular DataTable.
The simplest method to check if data exists in database on not, is to write an SQL Count statement e.g. SELECT COUNT(columnName) FROM tableName WHERE columnName = 'some value' . If 'sum value' doesn't exist in database it will return 0, return the count otherwise.
Basically DataSet is only a container of DataTable(s). If you want to find out about a particular data in DataTable instance inside DataSet instance, you can get DataTable instance from DataSet and there is an instance method called "Select" method (call it with parameter) to query specific data from DataTable instance.
i found on internet reference to:
Stack and
Find Data
My Bussines Layer:
public List<string> CompareInsee(string TheZone, List<object> InseList)
{
try
{
List<string> TempDict = new List<string>();
RempliClientInseExtracted(TheZone, ref NomTable);
DataTable TempDS = oClInse.Get_All_Inse(NomTable);
DataRow drFound;
DataColumn[] dcPk = new DataColumn[1];
// Set Primary Key
dcPk[0] = TempDS.Columns["NO_INSEE"];
TempDS.PrimaryKey = dcPk;
// Find the Row specified in txtFindArg
foreach (var oItem in InseList)
{
drFound = TempDS.Rows.Find(oItem);
if (drFound != null) TempDict.Add( oItem.ToString());
}
return TempDict;
}
catch (Exception excThrown)
{
if (!excThrown.Message.StartsWith("Err_")) { throw new Exception("Err_BL_ReadAllClientInsee", excThrown); }
else { throw new Exception(excThrown.Message, excThrown); }
}
}
Data Acces layer:
public DataTable Get_All_Inse(string NomTable)
{
try
{
using (var connectionWrapper = new Connexion())
{
var connectedConnection = connectionWrapper.GetConnected();
string sql_SelectAll = "SELECT * FROM " + NomTable;
SqlCommand comm_SelectAll = new SqlCommand(sql_SelectAll, connectionWrapper.conn);
SqlDataAdapter adapt_SelectAll = new SqlDataAdapter();
adapt_SelectAll.SelectCommand = comm_SelectAll;
DataTable dSet_SelectAll = new DataTable();
adapt_SelectAll.Fill(dSet_SelectAll);
dSet_SelectAll.Dispose();
adapt_SelectAll.Dispose();
return dSet_SelectAll;
}
}
catch (Exception excThrown)
{
if (!excThrown.Message.StartsWith("Err_")) { throw new Exception("Err_GetAllUsrClient", excThrown); }
else { throw new Exception(excThrown.Message, excThrown); }
}
}
So now i only have 1 loop --> just in my Bussines layer, NOT in DAL.
thanks you all
Related
Im trying to fill a listview with data from my database but get a null reference exception when i load the listview. Im using MVC pattern.
Code in my data acces layer:
public List<Menu_Item> DB_Get_All_MenuItems()
{
string query = "SELECT * FROM [Menu_Items]";
SqlParameter[] sqlParameters = new SqlParameter[0];
return ReadTables(ExecuteSelectQuery(query, sqlParameters));
}
private List<Menu_Item> ReadTables(DataTable dataTable)
{
List<Menu_Item> menu_items = new List<Menu_Item>();
foreach (DataRow dr in dataTable.Rows)
{
Menu_Item menu_Item = new Menu_Item()
{
Menu_ID = (int)dr["Menu_ID"],
Naam = (string)dr["Naam"],
Prijs = (float)dr["Prijs"],
Voorraad = (int)dr["Voorraad"],
Categorie_ID = (int)dr["Catogorie_ID"]
};
menu_items.Add(menu_Item);
}
return menu_items;
}
I have checked and my SQL parameters are all spelled correctly
The exact error is: datatable.rows = 'datatable.rows' threw an exception of type 'system.nullreferenceexception'
My DateTable method looks like this
protected DataTable ExecuteSelectQuery(string query, params SqlParameter[] sqlParameters)
{
SqlCommand command = new SqlCommand();
DataTable dataTable;
DataSet dataSet = new DataSet();
try
{
command.Connection = OpenConnection();
command.CommandText = query;
command.Parameters.AddRange(sqlParameters);
command.ExecuteNonQuery();
adapter.SelectCommand = command;
adapter.Fill(dataSet);
dataTable = dataSet.Tables[0];
}
catch (SqlException e)
{
return null;
throw new Exception(e.ToString());
}
finally
{
CloseConnection();
}
return dataTable;
}
Check whether dataTable null or not
if(dataTable!=null && dataTable.Rows.Count > 0)
{
foreach (DataRow dr in dataTable.Rows)
{
Menu_Item menu_Item = new Menu_Item()
{
Menu_ID = (int)dr["Menu_ID"],
Naam = (string)dr["Naam"],
Prijs = (float)dr["Prijs"],
Voorraad = (int)dr["Voorraad"],
Categorie_ID = (int)dr["Catogorie_ID"]
};
menu_items.Add(menu_Item);
}
}
check if the datarows.count is null or not ...
Also in DB_Get_All_MenuItems() mention dbconnction string, sql command type, and datareader and all...first make sure the datas is returning in this function o/p....
You are trying to use something that is null. This means you either set it to null, or you never set it to anything at all.
Now, You can then place a breakpoint at every found location and run your program with the debugger attached. Every time the debugger breaks on such a breakpoint, you need to determine whether you expect the reference to be non-null.
The below is a Static method written in java to populate a jtable with query of request.(Basically most queries can be executed and the method can populate the data- Includes where and joins clauses too)
Is there a similar way in C# to do this ? (Basically this method is from an external class(same package) to jframe then to jtable - So how can we do the same with C# class to Windows forms and then to data grid view).
The only good source I found was this but that's in mysql how can use the normal mssql methods and do this ? If someone can direct me to source that explains how to do this or give an example of how to do this with all Select, Insert & Update clauses it would be great.
public void searchData(JTable table, String Query)
{
try
{
stmt = con.createStatement();
rs = stmt.executeQuery(Query);
//To remove previously added rows
while (table.getRowCount() > 0)
{
((DefaultTableModel) table.getModel()).removeRow(0);
}
int columns = rs.getMetaData().getColumnCount();
while (rs.next())
{
Object[] row = new Object[columns];
for (int i = 1; i <= columns; i++)
{
row[i - 1] = rs.getObject(i);
}
((DefaultTableModel) table.getModel()).insertRow(rs.getRow() - 1, row);
}
rs.close();
stmt.close();
con.close();
}
catch (SQLException e)
{
}
}
In ADO.NET you build an SqlDataAdapter with your query and connection, initialize a DataTable variable instance and call the SqlDataAdapter.Fill method passing the DataTable variable. Your data is in the DataTable.
public DataTable searchData(string query)
{
try
{
DataTable table = new DataTable();
using(SqlConnection con = new SqlConnection(....constring here...))
{
using(SqlDataAdapter da = new SqlDataAdapter(query, con))
da.Fill(table);
}
return table;
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
return null;
}
}
Now I use method in C# to read table from SQLite database into DataTable,
but I want to send all table into other object.
So I think I have to use DataSet to combine all DataTable(s)
and send it to object as parameter.
Is there method that easy read all tables from SQLite database to DataSet?
Or I have to read all tables from SQLite database to DataTable each table
and combine to DataSet by hand?
The sql for listing all the tables is:
SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY 1
you could then get all the tables as databases seperately and then add them into a dataset - an example here: http://www.dotnetperls.com/dataset
so i guess the code would be something like:
Dataset d = new Dataset()
foreach (tableName in GetTables()){
d.Tables.Add(GetDataTable("select * from "+tableName);
}
code for GetTables and GetDataTable (i'll leave the piecing it together to you):
public ArrayList GetTables()
{
ArrayList list = new ArrayList();
// executes query that select names of all tables in master table of the database
String query = "SELECT name FROM sqlite_master " +
"WHERE type = 'table'" +
"ORDER BY 1";
try
{
DataTable table = GetDataTable(query);
// Return all table names in the ArrayList
foreach (DataRow row in table.Rows)
{
list.Add(row.ItemArray[0].ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return list;
}
public DataTable GetDataTable(string sql)
{
try
{
DataTable dt = new DataTable();
using (var c = new SQLiteConnection(dbConnection))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
return dt;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
I'm feeding a ReportDataSource with a query using Dapper.
However, I have an empty report, even with an IEnumerable loaded data.
When you spend a Datatable works.
How do I pass data from a query using Dapper for ReportViewer?
this.reportViewer.LocalReport.DataSources.Clear();
DataTable dt = new DataTable();
dt = CN.Query(Sql, param);
Microsoft.Reporting.WinForms.ReportDataSource rprtDTSource = new Microsoft.Reporting.WinForms.ReportDataSource(dt.TableName, dt);
this.reportViewer.LocalReport.DataSources.Add(rprtDTSource);
this.reportViewer.RefreshReport(); –
Looks like Dapper now supports the DataTable...
From the test:
public void ExecuteReader()
{
var dt = new DataTable();
dt.Load(connection.ExecuteReader("select 3 as [three], 4 as [four]"));
dt.Columns.Count.IsEqualTo(2);
dt.Columns[0].ColumnName.IsEqualTo("three");
dt.Columns[1].ColumnName.IsEqualTo("four");
dt.Rows.Count.IsEqualTo(1);
((int)dt.Rows[0][0]).IsEqualTo(3);
((int)dt.Rows[0][1]).IsEqualTo(4);
}
Also now supported is using a DataTable as a TableValueParameter:
public void DataTableParameters()
{
try { connection.Execute("drop proc #DataTableParameters"); } catch { }
try { connection.Execute("drop table #DataTableParameters"); } catch { }
try { connection.Execute("drop type MyTVPType"); } catch { }
connection.Execute("create type MyTVPType as table (id int)");
connection.Execute("create proc #DataTableParameters #ids MyTVPType readonly as select count(1) from #ids");
var table = new DataTable { Columns = { { "id", typeof(int) } }, Rows = { { 1 }, { 2 }, { 3 } } };
int count = connection.Query<int>("#DataTableParameters", new { ids = table.AsTableValuedParameter() }, commandType: CommandType.StoredProcedure).First();
count.IsEqualTo(3);
count = connection.Query<int>("select count(1) from #ids", new { ids = table.AsTableValuedParameter("MyTVPType") }).First();
count.IsEqualTo(3);
try
{
connection.Query<int>("select count(1) from #ids", new { ids = table.AsTableValuedParameter() }).First();
throw new InvalidOperationException();
} catch (Exception ex)
{
ex.Message.Equals("The table type parameter 'ids' must have a valid type name.");
}
}
As I could not find another way to feed my ReportViewer to a query Dapper.Query then downloaded the source and added the code below.
#region CODTEC SISTEMAS
/// <summary>
/// Return a typed list of objects, reader is closed after the call
/// </summary>
public static DataTable Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType)
{
var identity = new Identity(sql, commandType, cnn, typeof(DapperRow), param == null ? null : param.GetType(), null);
var info = GetCacheInfo(identity);
IDbCommand cmd = null;
IDataReader reader = null;
bool wasClosed = cnn.State == ConnectionState.Closed;
try
{
cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType);
if (wasClosed) cnn.Open();
reader = cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection : CommandBehavior.Default);
wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader
// with the CloseConnection flag, so the reader will deal with the connection; we
// still need something in the "finally" to ensure that broken SQL still results
// in the connection closing itself
DataTable dt = new DataTable();
dt.Load(reader);
// happy path; close the reader cleanly - no
// need for "Cancel" etc
reader.Dispose();
reader = null;
return dt;
}
finally
{
if (reader != null)
{
if (!reader.IsClosed) try { cmd.Cancel(); }
catch { /* don't spoil the existing exception */ }
reader.Dispose();
}
if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose();
}
}
#endregion
To Get the DataTable from SqliteDB using Dapper.
Pass the query such as "select*from table" inside the method.
list is formed, by executing query.
Then serialize the object into Json and then deserialize the Json
into the DataTable.
public DataTable method(string query)
{
string connection = #"Data Source= C:\User\DBFolder\sampleDB.db;Version=3;New=False;Compress=True;";
using (IDbConnection dbConnection = new SQLiteConnection(connection))
{
dbConnection.Open();
var output1 = dbConnection.Query(query).ToList();
dbConnection.Close();
var json = JsonConvert.SerializeObject(output1);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
return dt;
}
}
Not sure how Dapper works, but a datatable is binded like this:
DataTable dt = new DataTable();
DataColumn dc = dt.Columns.Add();
dc.ColumnName = "DataColumn1";
dc = dt.Columns.Add();
dc.ColumnName = "DataColumn2";
dt.Rows.Add(new object[] { "Frank", 32 });
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("DataSet1_DataTable1", dt));
this.reportViewer1.RefreshReport();
and since I am using C#, I bind data sources like this:
this.bindingSource1.DataSource = getListMethod(); // this method/property returns a list of objects
this.reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("Point", (this.bindingSource1)));
//Point is the datatable name in my Dataset.xsd file
I have Stored Procedure which returns Multiple tables as ResultSet. I Stored it in DataTable and Pass that DataTable Object to Another Form Which Print Tables In MY Web Page.
My Question is How Can i Stored Multiple ResultSet Returned from Stored Procedure into SINGLE DataTable Object Which I Can return to another function.
public static DataTable[] getGraphData(Int32 type)
{
SqlConnection oConn = null;
DataSet dsReturn = null;
DataTable[] dtReturn=new DataTable[2];
try
{
getConnection(ref oConn, 1);
using (SqlStoredProcedure sspObj = new SqlStoredProcedure("dbo.usp_getGraphData", oConn, CommandType.StoredProcedure))
{
sspObj.AddParameterWithValue("#Type", SqlDbType.Int, 0, ParameterDirection.Input, type);
dsReturn = sspObj.ExecuteDataSet();
dtReturn[0] = dsReturn.Tables[0];
dtReturn[1] = dsReturn.Tables[1];
dtReturn[2] = dsReturn.Tables[2];
sspObj.Dispose();
}
closeConnection(ref oConn);
}
catch (Exception xObj)
{
//dtReturn[] = new DataTable();
}
return dtReturn;
}
Function Which Takes the all three DataTables
DataTable dtOutput = Generix.getGraphData(type);
How to get Each DataTable From Here ? Means 0th Element to dtOutput1 , 1st Element to dtOutput2.....Like wise
Why don't you use a dataset as podiluska mentioned, and then access the DataSet.Tables property to gets your three table one by one.
If the three table structure is difderent does not make sense to foece them into a table. For this the DataSet is the better way. It is kind of collection of your table.
EDIT for the question about the DataTable[]:
DataTable[] dtOutputs = Generix.getGraphData(type);
//dtReturn[0]
DataTable dtOutput0 = dtOutputs[0];
//dtReturn[1]
DataTable dtOutput1 = dtOutputs[1];
//dtReturn[2]
DataTable dtOutput2 = dtOutputs[2];
Or if you need not only reference those table, but copy them, you can use .Copy() like:
//dtReturn[0]
DataTable dtOutput1 = dtOutputs[1].Copy;
I still think that the best way would be returning a DataSet by the query (it doesn't make sense to make a DataTable query from that.)
public static DataSet getGraphData(Int32 type)
{
SqlConnection oConn = null;
DataSet dsReturn = null;
try
{
getConnection(ref oConn, 1);
using (SqlStoredProcedure sspObj = new SqlStoredProcedure("dbo.usp_getGraphData", oConn, CommandType.StoredProcedure))
{
sspObj.AddParameterWithValue("#Type", SqlDbType.Int, 0, ParameterDirection.Input, type);
dsReturn = sspObj.ExecuteDataSet();
//You don't need Dispose() - because the using will do that on sspObj
}
closeConnection(ref oConn);
}
catch (Exception xObj)
{
dsReturn = new DataSet("Empty");
}
return dsReturn ;
}
And calling the method like this:
DataSet dsOutput = Generix.getGraphData(type);
//Simply a reference or Copy() the DataSet's tables:
DataTable dtOutput0 = dsOutput.Tables[0];
DataTable dtOutput1 = dsOutput.Tables[1];
DataTable dtOutput2 = dsOutput.Tables[2];
Use a union in your stored procedure to join the result sets together
ie:
SELECT * from yourtable WHERE name='bob'
UNION ALL
SELECT * from yourtable WHERE name='jane'
If you want to return your multiple tables into a single object, you can use a DataSet (which contains multiple tables) instead of a DataTable. You populate it in the same way.
eg:
DataSet dst = new DataSet();
new SqlAdapter(command).Fill (dst);