I am making a program in C# with access database. I want to check if a string from the database is in a string.
I have a table named keyword and I have a string who has some text in it. So, I want to check if any of the strings in the database is in the text, one by one.
Let's say I have this in my database:
"ABC", "CDE", "EFG"
and I have this text:
string a = "and abc asd dsa efg"
And I want to fill a label - if is true "The string has ABC, EFG" else "NO MATCH"
Thanks in advance,
dnisko
First populate table column values into a string List.
SqlConnection cnn = new SqlConnection(/*Database connection credentails*/);
SqlDataAdapter da = new SqlDataAdapter("select columnName from table", con);
DataSet ds = new DataSet();
da.Fill(ds);
List<string> keyValues= new List<string>();
foreach(DataRow row in ds.Tables[0].Rows)
{
keyValues.Add(row["columnName"].ToString());
}
Then search for string in text one by one.
string a = "and abc asd dsa efg";
string matchedKeys=string.Empty;
bool matchFound = false;
foreach(string key in keyValues)
{
if(a.Contains(key))
{
matchFound=true;
matchedKeys + = key + ",";
}
}
if(matchFound)
lbl.Text = "The string has " + matchedKeys;
else
lblText = " NO Match Found !";
will be easier to achieve on Database side. For SQL Server it will be like
#lookup as your parameter
SELECT k.Word FROM Keywords k
WHERE #lookup like '%' + k.Work + '%'
This will return you a collection of keywords that were found in the string you passed as parameter to this query string (stored procedure)
try to use this
// list from DB
var list = new List<string> { "ABC", "CDE", "EFG" };
var selectedResult = new List<string>();
var a = "and abc asd dsa efg";
list.ForEach(x =>
{
var result = a.ToUpperInvariant().Contains(x.ToUpperInvariant());
if (result)
{
selectedResult.Add(x);
}
});
var joined = selectedResult.Count > 0 ? string.Join(",", selectedResult) : "No Match";
Related
I can't seem to get this working:
My table column headers are 'genre' 'artist' 'album'
and the params I'm passing in are (type, filter, value) ("artist", "genre", "Rock") where there are two rows in the db with "Rock" for the genre.
When I follow the debugger, the 'while (reader.Read())' must return false because the loop is never entered and thus nothing written to the List.
public static List<String> getWithFilter(String type, String filter, String value)
{
List<String> columnData = new List<String>();
string query = "SELECT #type FROM Music WHERE" +
" #filter = '#value'";
SqlConnection connection = Database.GetConnection();
SqlCommand getData = new SqlCommand(query, connection);
getData.Parameters.AddWithValue("#type", type);
getData.Parameters.AddWithValue("#filter", filter);
getData.Parameters.AddWithValue("#value", value);
connection.Open();
using (connection)
{
using (getData)
{
using (SqlDataReader reader = getData.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetString(0));
}
}
}
}
return columnData;
}
You cannot use parameters for the names of columns and you don't put quotes around them when using them. Right now your query is the equivalent of
SELECT 'artist' FROM Music WHERE 'genre' = '#value'
You can do the following instead.
string query = "SELECT " + type + " FROM Music WHERE " + filter + " = #value";
And just remove the lines that create the #type and #fitler parameters.
You're looking either for formatting or string interpolation (requires C# 6.0):
string query =
$#"SELECT {type}
FROM Music
WHERE {filter} = #value";
...
getData.Parameters.AddWithValue("#value", value);
Formatting is a bit more wordy:
string query = String.Format(
#"SELECT {0}
FROM Music
WHERE {1} = #value", type, filter);
I assuming that you're using .net 2
DateTime current = DateTime.Now;
Console.WriteLine(current);
SqlConnection conn = new SqlConnection();
string q = "SELECT #field FROM student";
SqlDataAdapter da = new SqlDataAdapter(q, conn);
da.SelectCommand.Parameters.AddWithValue("#field", "snName");
DataTable dt = new System.Data.DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
List<string> names = new List<string>();
foreach (DataRow dr in dt.Rows)
{
names.Add(dr[0].ToString());
}
Console.WriteLine("Fetching {0} data for {1}", names.Count, DateTime.Now - current);
Console.ReadKey();
You can use lambda expression to mapping the datatable in .net >4
my first question on stackoverflow since I didn't find any solution yet:
I'm working on a simple password display tool which takes data from an MS Access DB (no proper DB available...)
The Access DB has two tables. A PC table and a passwords child table, linked via MAC Adress.
The Program displays a key/value list in a listbox with all the PC names retrieved via oledb.
key is the PC name, value is the MAC adress.
This works fine.
void cmdGetPCs()
{
OleDbDataAdapter daPCs = new OleDbDataAdapter();
OleDbConnection vcon = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;data source=H:\XXX\XXX\MYACCESSFILE.accdb;Jet OLEDB:Database Password=[REDACTED]");
const string q = "SELECT SISSI & ' (' & IP & ') - ' & DESCRIPTION as LONGDESCR, MAC from PC_LIST WHERE active = true order by sissi, ip"; //use & instead of + to have blankspace instead of null values for displaying PCs without Sissi because CONCAT doesn't work (MS Access....)
vcon.Open();
daPCs.SelectCommand = new OleDbCommand(q, vcon);
vcon.Close();
DataSet dsPC = new DataSet("PCs");
daPCs.MissingSchemaAction = MissingSchemaAction.AddWithKey;
daPCs.Fill(dsPC, "tblPCs");
DataTable dtPC = dsPC.Tables["tblPCs"];
var PCList = new List<PCInfo>();
foreach (DataRow dtRow in dtPC.Rows)
{
PCList.Add(new PCInfo() { LONGDESCR = dtRow["LONGDESCR"].ToString(), MAC = dtRow["MAC"].ToString() });
}
lstPCs.DisplayMember = "LONGDESCR";
lstPCs.ValueMember = "MAC";
lstPCs.DataSource = PCList;
}
So ok, I have a list filled with PC descriptions.
Now when I select an item from the Listbox I have a datagridview element in the same window that should be filled with the password info:
void ListBox1SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text = lstPCs.GetItemText(lstPCs.SelectedItem);
string x = lstPCs.GetItemText(lstPCs.SelectedValue);
//Dataset_get(x);
}
This still works fine as long as Dataset_get is commented out. First line displays the visible key of the item box as a header of a groupbox and string x is the MAC adress (=ItemList Value) of the selected Item.
As soon as I activate Dataset_get(x) and launch the program the ListBox is populated, but all items get replaced by item.toString() placeholders it seems.
Listbox just looks like:
myprogramname.MainForm+PCInfo
myprogramname.MainForm+PCInfo
myprogramname.MainForm+PCInfo
myprogramname.MainForm+PCInfo
myprogramname.MainForm+PCInfo
etc..
The first two lines (groupbox and string x) of the indexchange still work fine and display the right values.
Also Dataset_get itself is working fine and populating the Datagridview. So I can either have a user readable List box without filled datagrid view or a broken listbox with a filled datagrid view...
Obviously I need a readable list box with a filled datagrid view ;)
I narrowed down the issue in Dataset_get to the point that it starts to get broken as soon as the Fill line of the datagrid view data retrieving is called:
private void Dataset_get(string mymac)
{
OleDbDataAdapter daPass = new OleDbDataAdapter();
OleDbConnection vconp = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;data source=H:\XXX\XXX\MYACCESSFILE.accdb;Jet OLEDB:Database Password=[REDACTED]");
string qp = "";
switch (mypermissions)
{
case "ADMIN":
qp = "SELECT USER_TYPE, HAS_ADMIN, USER_NAME, PASSWORD, ID FROM PASSWORDS WHERE ID = '" + mymac + "' ORDER BY user_type";break;
case "USER":
qp = "SELECT p.USER_TYPE, p.HAS_ADMIN, p.USER_NAME, p.PASSWORD, p.ID FROM PASSWORDS p, PC_LIST pc WHERE p.ID = '" + mymac + "' and p.ID = pc.MAC and (pc.x_plant like '%USER%' or (ucase(p.user_type) not like '%ADMIN%')) ORDER BY p.user_type";break;
default: break;
}
vconp.Open();
daPass.SelectCommand = new OleDbCommand(qp, vconp);
vconp.Close();
DataSet dsPass = new DataSet("Passwords");
daPass.MissingSchemaAction = MissingSchemaAction.AddWithKey;
daPass.Fill(dsPass,"tblPass"); //REPLACEMENT OF LIST ITEMS IS TRIGGERED BY THIS LINE
DataTable dtPass = dsPass.Tables["tblPass"];
dataGridView1.DataSource = dtPass;
}
Please help me... Thanks in advance!
PS: The datagridview is in a group box while the listbox isn't, but that doesn't make any difference I guess.
Solved it with the help of Reza Aghaeis answer at Get the value for a listbox item by index
public static class ListControlExtensions
{
public static object GetItemValue(this ListControl list, object item)
{
if (item == null)
throw new ArgumentNullException("item");
if (string.IsNullOrEmpty(list.ValueMember))
return item;
var property = TypeDescriptor.GetProperties(item)[list.ValueMember];
if (property == null)
throw new ArgumentException(
string.Format("item doesn't contain '{0}' property or column.",
list.ValueMember));
return property.GetValue(item);
}
}
//.........................................
void cmdGetPCs()
{
const string q = "SELECT SISSI & ' (' & IP & ') - ' & DESCRIPTION as LONGDESCR, MAC from PC_LIST WHERE active = true order by sissi, ip"; //use & instead of + to have blankspace instead of null values for displaying PCs without Sissi because CONCAT doesn't work (MS Access....)
OleDbDataAdapter da = new OleDbDataAdapter();
DataSet ds = new DataSet();
vcon.Open();
da.SelectCommand = new OleDbCommand(q, vcon);
vcon.Close();
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
da.Fill(ds, "tblPCs");
DataTable dtPC = ds.Tables["tblPCs"];
foreach (DataRow dtRow in dtPC.Rows)
{
lstPCs.Items.Add(new KeyValuePair<String, String>(dtRow["LONGDESCR"].ToString(), dtRow["MAC"].ToString()));
}
lstPCs.DisplayMember = "Key";
lstPCs.ValueMember = "Value";
}
//.........................................
private void Dataset_get(string mymac)
{
string qp = "";
switch (mypermissions)
{
case "ADMIN":
qp = "SELECT USER_TYPE, HAS_ADMIN, USER_NAME, PASSWORD FROM PASSWORDS WHERE ID = '" + mymac + "' ORDER BY user_type";break;
case "USER":
qp = "SELECT p.USER_TYPE, p.HAS_ADMIN, p.USER_NAME, p.PASSWORD FROM PASSWORDS p, PC_LIST pc WHERE p.ID = '" + mymac + "' and p.ID = pc.MAC and (pc.x_plant like '%USER%' or (ucase(p.user_type) not like '%ADMIN%')) ORDER BY p.user_type";break;
default: break;
}
OleDbDataAdapter dapass = new OleDbDataAdapter();
DataSet dspass = new DataSet();
vcon.Open();
dapass.SelectCommand = new OleDbCommand(qp, vcon);
vcon.Close();
dapass.MissingSchemaAction = MissingSchemaAction.AddWithKey;
dapass.Fill(dspass,"tblPass");
DataTable dtPass = new DataTable();
dtPass = dspass.Tables["tblPass"];
dataGridView1.DataSource = dtPass;
}
//.........................................
void ListBox1SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text = lstPCs.GetItemText(lstPCs.SelectedItem);
string x = lstPCs.GetItemValue(lstPCs.SelectedItem).ToString();
Dataset_get(x);
}
OleDbConnection vcon is shared.
I have requirement where I have to perform calculation on textbox based on formula. I wanted to know how to get the field name and operators separately so that i can bind it in formula textbox. Example : {FieldName1} + {FieldName2}+{Fieldname3} is the formula and i want the data which contains braces separately as they will taken as field name and + symbol separately. I dont know how to get this. Here is my code-
DataTable dt_main = GetTable();
DataTable dt_AutocalculatedColumns = GetCalculatedColumn();
string AutoGeneratedColumnName = string.Empty;
string Formula = string.Empty;
string FLD1 = string.Empty;
string FLD2 = string.Empty;
string FLD3 = string.Empty;
if (dt_AutocalculatedColumns.Rows.Count > 0)
{
foreach (DataRow row_field in dt_AutocalculatedColumns.Rows)
{
AutoGeneratedColumnName = row_field["FieldName"].ToString();
Formula = row_field["AutoCalculatedFormula"].ToString();
string[] words = Formula.Split(' ');
foreach (string Eachword in words)
{
// what to do here i am not getting
}
}
}
protected DataTable GetCalculatedColumn()
{
SqlConnection con= newSqlConnection(ConfigurationManager.ConnectionStrings["ExcelLikeConnnectionString"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("My Select Query", con);
cmd.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
return dt;
}
Any help would be appreciated. Thanks in advance
If you're using only + operator then you should split on it and not on ' '. To make sure that you don't have field name with spaces use trim.
string[] words = Formula.Split('+');
for (int i = 0; i < words.Length; i++)
{
words[i] = words[i].Trim();
}
Of course in this situation you can't have + in field names.
You can also use LINQ:
string formula = "{FieldName1} + {FieldName2}+{Fieldname3}";
string[] words = formula.Split('+')
.Select(w => w.Trim(new char[] {' ', '{', '}'})).ToArray();
This will split the string formula and trim each entry so that you are just left with your field names. The resulting output would be a 3 element array containing FieldName1, FieldName2, and FieldName3.
If I have a list of Strings, ie. List<String>, how can I generate a SQL statement such as:
SELECT Column1 FROM Table1 WHERE Column1 IN ('String1','String2','String3')
where 'String1','String2','String3' are the contents of List<String>?
No LINQ etc. as I am using VS2005.
Take a look on following version
[Test]
public void Test()
{
var list = new List<string> {"String1", "String2", "String3"};
string values = ArrayToString(list);
string sql = string.Format("SELECT Column1 FROM Table1 WHERE Column1 IN ( {0} )", values);
}
private static string ArrayToString(IEnumerable<string> array)
{
var result = new StringBuilder();
foreach (string element in array)
{
if (result.Length > 0)
{
result.Append(", ");
}
result.Append("'");
result.Append(element);
result.Append("'");
}
return result.ToString();
}
result statement SELECT Column1 FROM Table1 WHERE Column1 IN ( 'String1', 'String2', 'String3' )
List<string> lst=new List<string>();lst.Add("Hello");lst.Add("Hello World");
string s="";
foreach(string l in lst)s+="\""+l+"\"";
s=Regex.Replace(s,"\"\"","\",\"");
string output="SELECT Column1 FROM Table1 WHERE Column1 ("+s+")";
try :
List<String> strlist = new List<string>();
strlist.Add("st1");
strlist.Add("st2");
strlist.Add("st3");
string query = "SELECT Column1 FROM Table1 WHERE Column1 IN (";
for (int i = 0; i < strlist.Count; i++)
{
query += "\'" + strlist[i] + "\'" + (i == strlist.Count - 1 ? "" : ",");
}
query += ")";
List<string> items = new List<string>();
items.Add("string1");
items.Add("string2");
items.Add("string3");
string AllItems = "";
foreach (string item in items)
{
AllItems += string.Format("\"{0}\",",item);
}
AllItems = AllItems.TrimEnd(',');
string YourSQLQuery = string.Format("SELECT Column1 FROM Table1 WHERE Column1 IN ({0})", AllItems);
MessageBox.Show(YourSQLQuery);
Don't for get to guard against SQL Injection.
string sql_list = "";
foreach (string s in lst)
sql_list+=string.Format("{0},",s.Replace("'","''"));
sql_list = string.Format("({0})",sql_list.substring(0,sql_list.length-2));
that might help some, and use string builder, or not.
Please don't use the other answers that have been submitted so far. They contain SQL injection for no obvious reason.
List<String> strlist = new List<string>();
strlist.Add("st1");
strlist.Add("st2");
strlist.Add("st3");
var dynamicPart = string.Join(", ",
Enumerable.Range(0, strlist.Count).Select(i => "#" + i).ToArray());
for(i = 0 to strlist.Count)
{ /* add parameter to SqlCommand here with name ("#" + i) */ }
string query = "SELECT Column1 FROM Table1 WHERE Column1 IN (" +
dynamicPart + ")";
Use parameters instead of literals for multiple reasons (research them!).
And instead of a clumsy concatenation loop use string.Join which does all of that for us.
To properly handle sql injection, a better answer may be to make the query of the form...
select results.* from (
select pk from table where column=value1 union
select pk from table where column=value2 union
select pk from table where column=value3 union
select pk from table where column=value4 union
select pk from table where column=value5
) filtered join table as results on filtered.pk = results.pk
and then make it more c# friendly
string items_filter = "";
int item_index=0;
OracleParameterCollection parameters = new OracleParameterCollection(); // Not sure what class to use here exactly, but just collect a bunch of stored procedure parameters
foreach (string item in list_of_items) {
string item_name = string.Format("i_item{0}",item_index);
string item_sql = string.Format("select pk from table where column=:{0} union",item_name);
parameters.Add(new Parameter("item_name",item));
item_index+=1;
}
if (items_filter.IsNullOrEmpty())
return;
string sql = String.Format("select results.* from ({0}) filtered join table as results on filtered.pk = results.pk",items_filter);
OracleCommand c = new OracleCommand();
c.command = sql;
c.parameters = parameters;
c.execute();
More or less.
Since you said its an internal operation and hence there is no need to be worried about SQL Injection, then you can achieve what you want by this.
string str = "";
foreach(string s in list)
str += "'" + s.Replace("'", "''") + "',";
str = str.SubString(0, str.Length - 1);
str = "SELECT Column1 FROM Table1 WHERE Column1 IN (" + str + ")";
//str will have your command ready.
I have tested it. It works perfectly.
// Assume your list (List<string>) is named "myList"
// Please put the next line in an external string resource...
string selectStatement = "SELECT Column1 FROM Table1 WHERE Column1 IN ({0})";
StringBuilder stringBuilder = new StringBuilder("(");
foreach(string colName in myList)
stringBuilder.Append(String.Format("'{0}',", colName));
stringBuilder.Append(")");
return String.Format(selectStatement, stringBuilder.ToString().Replace(",)", ")");
I want to show the single column value to gridview different column..
For example :
My column value is "Casual Leave:12-Medical Leave :13-Annual Leave :03" ..
I want to split the above string value and show the above values in a grid colulmn like this...
Employee Id Employee Name Casual Leave Medical Leave Annual Leave
00624323 James 12 13 03
00624324 Fernando 12 14 05
Note: Employee Id and Employee Name are different column
My partial code is here :
DataSet5TableAdapters.sp_getallempleaveTableAdapter TA = new DataSet5TableAdapters.sp_getallempleaveTableAdapter();
DataSet5.sp_getallempleaveDataTable DS = TA.GetData();
if (DS.Rows.Count > 0)
{
DataView datavw = new DataView();
datavw = DS.DefaultView;
datavw.RowFilter = "fldempid='" + txtempid.Text + "' and fldempname='" + txtempname.Text + "'";
if (datavw.Count > 0)
{
string leavehistory = Convert.ToString(datavw[0]["fldleavehistory"]);
string[] textarray = leavehistory.Split('-');
foreach (string samtext in textarray)
{
if (samtext.StartsWith(leavehistory))// I want to check the string with array value
{
string newtext = samtext.Split(':')[1];
}
}
}
}
what i do? please help me to solve this
Having such a compound column in your database is never a good idea. Why don't you just split the column into 3 columns (CasualLeave, MedicalLeave and AnnualLeave), each containing a number?
With the leavehistory and newtext either you can make a datatable and bind it to gridview or u can change your sp to directly return splitted result.
since u have coded so much in client side its now better to make a new datatable and feed rows into it and add this datatable to the gridsource
Edit :-
Example :-
DataTable newdatatable = new DataTable("New");
newdatatable.Columns.Add("Employee Id");
newdatatable.Columns.Add("Employee Name");
newdatatable.Columns.Add("Casual Leave");
newdatatable.Columns.Add("Medical Leave");
newdatatable.Columns.Add("Annual Leave");
newdatatable.AcceptChanges();
DataSet5TableAdapters.sp_getallempleaveTableAdapter TA = new DataSet5TableAdapters.sp_getallempleaveTableAdapter();
DataSet5.sp_getallempleaveDataTable DS = TA.GetData();
if (DS.Rows.Count > 0)
{
DataView datavw = new DataView();
datavw = DS.DefaultView;
datavw.RowFilter = "fldempid='" + txtempid.Text + "' and fldempname='" + txtempname.Text + "'";
if (datavw.Count > 0)
{
string leavehistory = Convert.ToString(datavw[0]["fldleavehistory"]);
string[] textarray = leavehistory.Split('-');DataRow drow = newdatatable.NewRow();
drow[0]=txtempid.Text;
drow[1]=txtempname.Text;
foreach (string samtext in textarray)
{
if (samtext.StartsWith(leavehistory))// I want to check the string with array value
{
drow[samtext.Split(':')[0]]=samtext.Split(':')[1];
}
}
newdatatable.Rows.Add(drow);
newdatatable.AcceptChanges();
}
}
gridview1.DataSource=newdatatable;