I have an string array (query.Tags) for filter a list of values and each time, procces just take the first value of string array during the query execution.
I tried several combinations but nothing changed. Of course, I tested all of these SQL statements in SQL SERVER View.
Can you tell me what I doing wrong?
public IEnumerable<ActorDto> SearchMembersInLists(ListMembersQuery query)
{
IEnumerable<ActorDto> result = null;
var sql = #"select DISTINCT t.ActorId,
a.Id, a.TypeId, a.Name, a.Identifier
FROM [ActorTag] t
INNER JOIN [Actor] a ON t.ActorId = a.Id
where t.Name IN #tags
";
using (var cnx = DbConnectionFactory.GetDefault().GetConnection())
{
cnx.Open();
var query_result = cnx.QueryMultiple(sql, new { query.Tags});
result = query_result.Read<ActorDto>();
}
return result;
}
the original code is this, i just tried to simplify as I could
public IEnumerable<ActorDto> SearchMembersInLists(ListMembersQuery query)
{
IEnumerable<ActorDto> result = null;
var sql = #"
SELECT DISTINCT a.Id, a.TypeId, a.Name, a.Identifier,a.Description, a.Email, a.PictureUrl, a.DisplayName --Actor
FROM [RoleMember] lm
INNER JOIN [Actor] a ON lm.ActorId = a.Id
WHERE {tag_filter} {lists_filter}
ORDER BY a.DisplayName DESC OFFSET #pageIndex ROWS FETCH NEXT #pageSize ROWS ONLY
";
bool has_tags = true;
bool has_lists = true;
if (query.Tags != null && query.Tags.Any())
{
sql = sql.Replace("{tag_filter}", "a.Id IN (SELECT t.ActorId FROM [ActorTag] t WHERE t.Name IN #tags)");
has_tags = true;
}
else
{
sql = sql.Replace("{tag_filter}", "");
has_tags = false;
}
if (query.Lists != null && query.Lists.Any())
{
if (has_tags)
{
sql = sql.Replace("{lists_filter}", "AND lm.RoleId IN #lists");
}
else
{
sql = sql.Replace("{lists_filter}", "lm.RoleId IN #lists");
}
has_lists = true;
}
else
{
sql = sql.Replace("{lists_filter}", "");
has_lists = false;
}
if (!has_tags && !has_lists){
sql = sql.Replace("WHERE", "");
}
var values = new
{
lists = query.Lists,
tags = query.Tags,
pageIndex = query.PageIndex * query.PageSizeOrDefault,
pageSize = query.PageSizeOrDefault
};
using (var cnx = DbConnectionFactory.GetDefault().GetConnection())
{
cnx.Open();
result = cnx.Query<ActorDto>(sql, values);
}
return result;
}
There is nothing wrong in the code shown, assuming you're using the latest version of dapper. A similar example is shown below (that can be run in a console exe etc). Please check your data is what you expect.
Note; the query code can actually be significantly simplified, but I wanted to keep it as similar to your example as possible. The simple alternative is here:
public static IEnumerable<ActorDto> SearchMembersInLists(ListMembersQuery query)
{
using (var cnx = GetConnection())
{
return cnx.Query<ActorDto>(
#"select Id, Name from FooActors where Name IN #Tags", new { query.Tags });
}
}
The full program with the more complex query layout is shown below. The output is:
2: Barney
4: Betty
using Dapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main()
{
// reset and populate
using (var conn = GetConnection())
{
conn.Open();
try { conn.Execute(#"drop table FooActors;"); } catch { }
conn.Execute(#"create table FooActors (
Id int not null primary key identity(1,1),
Name nvarchar(50) not null);");
conn.Execute(#"insert FooActors(Name) values(#Name);", new[]
{
new { Name = "Fred" },
new { Name = "Barney" },
new { Name = "Wilma" },
new { Name = "Betty" },
});
}
// run a demo query
var tags = new[] { "Barney", "Betty" };
var query = new ListMembersQuery { Tags = tags };
var actors = SearchMembersInLists(query);
foreach(var actor in actors)
{
Console.WriteLine("{0}: {1}", actor.Id, actor.Name);
}
}
public static IDbConnection GetConnection()
{
return new SqlConnection(
#"Initial Catalog=master;Data Source=.;Integrated Security=SSPI;");
}
public class ActorDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ListMembersQuery
{
public string[] Tags { get; set; }
}
public static IEnumerable<ActorDto> SearchMembersInLists(ListMembersQuery query)
{
IEnumerable<ActorDto> result = null;
const string sql = #"select Id, Name from FooActors where Name IN #Tags";
using (var cnx = GetConnection())
{
cnx.Open();
var query_result = cnx.QueryMultiple(sql, new { query.Tags });
result = query_result.Read<ActorDto>();
}
return result;
}
}
Related
How can I convert BestellingAantal ToString because I get an error whats says cannot convert type string to bool even I made it a int? It is for a loginsystem with C#
String strSQL;
strSQL =
"SELECT BestellingId, BestellingProductId, BestellingAantal " +
"FROM bestellingen";
oCommand = new MySqlCommand(strSQL, oConnection);
oDataReader = oCommand.ExecuteReader();
//De gegevens staan per record/rij in object DataReader
//Controleer of er data bestaat alvorens verder te gaan
if (oDataReader.HasRows)
{
//lees rij per rij uit DataReader object
//oDataReader.Read krijgt de waarde False,
// indien er geen record meer is
while (oDataReader.Read())
{
int BestellingId = (int)oDataReader["BestellingId"];
int BestellingProductId = (int)oDataReader["BestellingProductId"];
int BestellingAantal = (int)oDataReader["BestellingAantal"];
Bestelling oBestelling = new Bestelling();
oBestelling.BestellingId = BestellingId.ToString();
oBestelling.BestellingProductId = BestellingProductId.ToString();
oBestelling.BestellingAantal = BestellingAantal.ToString();
BestellingLijst.Add(oBestelling);
}
}
oConnection.Close();
if (huidigeGebruiker.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
{
String Email = String.Parse(huidigeGebruiker.Claims.FirstOrDefault(c => c.Type == ClaimTypes.).Value);
}
return BestellingLijst;
}
}
}
Are you averse to using Dapper? It's a great micro ORM that lets you carry on writing SQL, but do away with all this tedious crap of reading and casting things with datareaders, opening and closing conenctions etc.. you just write an SQL that maps to an object in your c# and get dapper to run the SQL and build a (list of) objects for you.. Like this:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Dapper;
using MySql.Data.MySqlClient;
using System.Security.Permissions;
public class Program
{
public static void Main()
{
string _connectionString = "Server=127.0.0.1;Database=Bestellingen;Uid=root;Pwd=pwd;";
var service = new BestellingenService(_connectionString);
var result = service.GetBestellingens();
foreach(var item in result)
{
Console.WriteLine(item.BestellingId);
}
}
}
//a class that represents the rows in your db table
public class Bestellingen
{
public int BestellingId { get; set; }
public int BestellingProductId { get; set; }
public int BestellingAantal { get; set; }
}
//a service that runs SQLs and returns you (lists of) your data mapping class
public class BestellingenService
{
private readonly MySqlConnection _conn;
public BestellingenService(string connStr)
{
_conn = new MySqlConnection(connStr);
}
public IEnumerable<Bestellingen> GetBestellingens()
{
var sql = "SELECT BestellingId, BestellingProductId, BestellingAantal FROM bestellingen";
var result = this._conn.Query<Bestellingen>(sql).ToList();
return result;
}
public Bestellingen GetBestellingenById(int bid)
{
var sql = "SELECT BestellingId, BestellingProductId, BestellingAantal FROM bestellingen WHERE id = #pBestellingId";
var result = this._conn.Query<Bestellingen>(sql, new { pBestellingId = bid }).FirstOrDefault();
return result;
}
}
I'm writing new api call for my android app, I want to retrieve data from dynamic table, I mean when user select "A" button from Andriod I want to retrieve data from "A" table and if "B" is click , retrieve data from "B" table. Someone help me to find the possible solution.
I want to replace with variable for "JBCTNRITEMs" from entities.JBCTNRITEMs (table-name)
var query = (from jbct in entities.JBCTNRITEMs
where jbid.Contains(jbct.jbid.ToString()) && boxid.Contains(jbct.TrackingNo.ToString())
select jbct).ToArray();
int id = 0;
if (query.Length > 0)
{
id = (query[0].id);
}
return id;
Here are the two different possibilities as an example
if (module.ToLower() == "module-a")
{
var imageinfo = (from jb in entities.TableA.AsEnumerable()
where scanID.Contains(jb.aid.ToString())
select jb).ToArray();
InsertGENIMAGE(userID, scanID, FilePath, imageinfo, "AIMAGE");
}
else if (module.ToLower() == "module-b")
{
var imageinfo = (from jb in entities.TableB.AsEnumerable()
where scanID.Contains(jb.bid.ToString())
select jb).ToArray();
InsertGENIMAGE(userID, scanID, FilePath, imageinfo, "BIMAGE");
}
Here, query stores what you are you trying to select. As long as you are trying to select same type or same anonymous type, it will work.
Here is a simple example:
class Test1
{
public int ID { get; set; }
public string Name { get; set; }
}
class Test2
{
public int ID { get; set; }
public string Name { get; set; }
}
var test1Lst = new List<Test1>
{
new Test1() { ID = 1, Name = "Jitendra" },
new Test1() { ID = 2, Name = "Jahnavi" }
};
var test2Lst = new List<Test2>
{
new Test2() { ID = 1, Name = "Aaditri" },
new Test2() { ID = 2, Name = "Pankaj" }
};
var test = false;
var query = test ? (from t in test1Lst select new { ID = t.ID, Name = t.Name }) : (from t in test2Lst select new { ID = t.ID, Name = t.Name });
// Put whatever condition you want to put here
query = query.Where(x => x.ID == 1);
foreach(var t1 in query)
{
Console.WriteLine(t1.ID + " " + t1.Name);
}
I guess in this case I would suggest to use a generic method :
private T GetMeTheFirstEntry<T>(Expression<Func<T, bool>> filter) where T : class
{
return entities.GetTable<T>().FirstOrDefault(filter);
}
The GetTable will allow you to interchange the tableA and tableB. You would call it the following way:
TableA tableA_entity = GetMeTheFirstEntry<TableA>(jb => scanID.Contains(jb.aid.ToString()));
TableB tableB_entity = GetMeTheFirstEntry<TableB>(jb => scanID.Contains(jb.bid.ToString()));
If the filtering was successfull, then the retrieved object will not be null and you can use it:
int a_id = tableA_entity.aid;
As the title says my intention is to find all tables participating in either INSERT/UPDATE/DELETE statements and produce a structured format. So far this is what I've come up with -
void Main()
{
string DBName = "Blah";
string ServerName = #"(localdb)\MSSQLLocalDB";
Server s = new Server(ServerName);
Database db = s.Databases[DBName];
ConcurrentDictionary<string, SPAudit> list = new ConcurrentDictionary<string, SPAudit>();
var sps = db.StoredProcedures.Cast<StoredProcedure>()
.Where(x => x.ImplementationType == ImplementationType.TransactSql && x.Schema == "dbo")
.Select(x => new
{
x.Name,
Body = x.TextBody
}).ToList();
Parallel.ForEach(sps, item =>
{
try
{
ParseResult p = Parser.Parse(item.Body);
IEnumerable<SqlInsertStatement> insStats = null;
IEnumerable<SqlUpdateStatement> updStats = null;
IEnumerable<SqlDeleteStatement> delStats = null;
var listTask = new List<Task>();
listTask.Add(Task.Run(() =>
{
insStats = FindBatchCollection<SqlInsertStatement>(p.Script.Batches);
}));
listTask.Add(Task.Run(() =>
{
updStats = FindBatchCollection<SqlUpdateStatement>(p.Script.Batches);
}));
listTask.Add(Task.Run(() =>
{
delStats = FindBatchCollection<SqlDeleteStatement>(p.Script.Batches);
}));
Task.WaitAll(listTask.ToArray());
foreach (var ins in insStats)
{
var table = ins?.InsertSpecification?.Children?.FirstOrDefault();
if (table != null)
{
var tableName = table.Sql.Replace("dbo.", "").Replace("[", "").Replace("]", "");
if (!tableName.StartsWith("#"))
{
var ll = list.ContainsKey(item.Name) ? list[item.Name] : null;
if (ll == null)
{
ll = new SPAudit();
}
ll.InsertTable.Add(tableName);
list.AddOrUpdate(item.Name, ll, (key, old) => ll);
}
}
}
foreach (var ins in updStats)
{
var table = ins?.UpdateSpecification?.Children?.FirstOrDefault();
if (table != null)
{
var tableName = table.Sql.Replace("dbo.", "").Replace("[", "").Replace("]", "");
if (!tableName.StartsWith("#"))
{
var ll = list.ContainsKey(item.Name) ? list[item.Name] : null;
if (ll == null)
{
ll = new SPAudit();
}
ll.UpdateTable.Add(tableName);
list.AddOrUpdate(item.Name, ll, (key, old) => ll);
}
}
}
foreach (var ins in delStats)
{
var table = ins?.DeleteSpecification?.Children?.FirstOrDefault();
if (table != null)
{
var tableName = table.Sql.Replace("dbo.", "").Replace("[", "").Replace("]", "");
if (!tableName.StartsWith("#"))
{
var ll = list.ContainsKey(item.Name) ? list[item.Name] : null;
if (ll == null)
{
ll = new SPAudit();
}
ll.DeleteTable.Add(tableName);
list.AddOrUpdate(item.Name, ll, (key, old) => ll);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
});
}
IEnumerable<T> FindBatchCollection<T>(SqlBatchCollection coll) where T : SqlStatement
{
List<T> sts = new List<T>();
foreach (var item in coll)
{
sts.AddRange(FindStatement<T>(item.Children));
}
return sts;
}
IEnumerable<T> FindStatement<T>(IEnumerable<SqlCodeObject> objs) where T : SqlStatement
{
List<T> sts = new List<T>();
foreach (var item in objs)
{
if (item.GetType() == typeof(T))
{
sts.Add(item as T);
}
else
{
foreach (var sub in item.Children)
{
sts.AddRange(FindStatement<T>(item.Children));
}
}
}
return sts;
}
public class SPAudit
{
public HashSet<string> InsertTable { get; set; }
public HashSet<string> UpdateTable { get; set; }
public HashSet<string> DeleteTable { get; set; }
public SPAudit()
{
InsertTable = new HashSet<string>();
UpdateTable = new HashSet<string>();
DeleteTable = new HashSet<string>();
}
}
Now I'm facing two problems
First, its is taking hell lot of a time to complete, given that there are around 841 stored procedures in the database.
Second, if there are statements like the following the table name is not being captured properly, meaning that the table is being captured as w instead of SomeTable_1 or SomeTable_2.
CREATE PROCEDURE [dbo].[sp_blah]
#t SomeTableType READONLY
AS
DELETE w
FROM SomeTable_2 w
INNER JOIN (Select * from #t) t
ON w.SomeID = t.SomeID
DELETE w
FROM SomeTable_1 w
INNER JOIN (Select * from #t) t
ON w.SomeID = t.SomeID
RETURN 0
Any help would be greatly appreciated.
Edit
Using the following dll from this location C:\Program Files (x86)\Microsoft SQL Server\140\DTS\Tasks-
Microsoft.SqlServer.ConnectionInfo.dll
Microsoft.SqlServer.Management.SqlParser.dll
Microsoft.SqlServer.Smo.dll
Microsoft.SqlServer.SqlEnum.dll
Finally I got it to work like I wanted the output to look like using #dlatikay answer. I'm posting this here more for documentation purposes than anything else.
I'm using the following nuget packages -
https://www.nuget.org/packages/Microsoft.SqlServer.SqlManagementObjects/
https://www.nuget.org/packages/Microsoft.SqlServer.TransactSql.ScriptDom/
and removed all other local dependencies. I hope this helps someone out there.
void Main()
{
string DatabaseName = "Blah";
string ServerIP = #"(localdb)\MSSQLLocalDB";
List<string> ExcludeList = new List<string>()
{
"sp_upgraddiagrams",
"sp_helpdiagrams",
"sp_helpdiagramdefinition",
"sp_creatediagram",
"sp_renamediagram",
"sp_alterdiagram",
"sp_dropdiagram"
};
List<string> StringDataTypes = new List<string>()
{
"nvarchar",
"varchar",
"nchar",
"char",
};
Server s = new Server(ServerIP);
s.SetDefaultInitFields(typeof(StoredProcedure), "IsSystemObject");
Database db = s.Databases[DatabaseName];
Dictionary<string, SPAudit> AuditList = new Dictionary<string, SPAudit>();
var sps = db.StoredProcedures.Cast<StoredProcedure>()
.Where(x => x.ImplementationType == ImplementationType.TransactSql && x.Schema == "dbo" && !x.IsSystemObject)
.Select(x => new
{
x.Name,
Body = x.TextBody,
Parameters = x.Parameters.Cast<StoredProcedureParameter>().Select(t =>
new SPParam()
{
Name = t.Name,
DefaultValue = t.DefaultValue,
DataType = $"{t.DataType.Name}{(StringDataTypes.Contains(t.DataType.Name) ? $"({(t.DataType.MaximumLength > 0 ? Convert.ToString(t.DataType.MaximumLength) : "MAX")})" : "")}"
})
}).ToList();
foreach (var item in sps)
{
try
{
TSqlParser parser = new TSql140Parser(true, SqlEngineType.Standalone);
IList<ParseError> parseErrors;
TSqlFragment sqlFragment = parser.Parse(new StringReader(item.Body), out parseErrors);
sqlFragment.Accept(new OwnVisitor(ref AuditList, item.Name, item.Parameters));
}
catch (Exception ex)
{
//Handle exception
}
}
}
public class OwnVisitor : TSqlFragmentVisitor
{
private string spname;
private IEnumerable<SPParam> parameters;
private Dictionary<string, SPAudit> list;
public OwnVisitor(ref Dictionary<string, SPAudit> _list, string _name, IEnumerable<SPParam> _parameters)
{
list = _list;
spname = _name;
parameters = _parameters;
}
public override void ExplicitVisit(InsertStatement node)
{
NamedTableReference namedTableReference = node?.InsertSpecification?.Target as NamedTableReference;
if (namedTableReference != null)
{
string table = namedTableReference?.SchemaObject.BaseIdentifier?.Value;
if (!string.IsNullOrWhiteSpace(table) && !table.StartsWith("#"))
{
if (!list.ContainsKey(spname))
{
SPAudit ll = new SPAudit();
ll.InsertTable.Add(table);
ll.Parameters.AddRange(parameters);
list.Add(spname, ll);
}
else
{
SPAudit ll = list[spname];
ll.InsertTable.Add(table);
}
}
}
base.ExplicitVisit(node);
}
public override void ExplicitVisit(UpdateStatement node)
{
NamedTableReference namedTableReference;
if (node?.UpdateSpecification?.FromClause != null)
{
namedTableReference = node?.UpdateSpecification?.FromClause?.TableReferences[0] as NamedTableReference;
}
else
{
namedTableReference = node?.UpdateSpecification?.Target as NamedTableReference;
}
string table = namedTableReference?.SchemaObject.BaseIdentifier?.Value;
if (!string.IsNullOrWhiteSpace(table) && !table.StartsWith("#"))
{
if (!list.ContainsKey(spname))
{
SPAudit ll = new SPAudit();
ll.UpdateTable.Add(table);
ll.Parameters.AddRange(parameters);
list.Add(spname, ll);
}
else
{
SPAudit ll = list[spname];
ll.UpdateTable.Add(table);
}
}
base.ExplicitVisit(node);
}
public override void ExplicitVisit(DeleteStatement node)
{
NamedTableReference namedTableReference;
if (node?.DeleteSpecification?.FromClause != null)
{
namedTableReference = node?.DeleteSpecification?.FromClause?.TableReferences[0] as NamedTableReference;
}
else
{
namedTableReference = node?.DeleteSpecification?.Target as NamedTableReference;
}
if (namedTableReference != null)
{
string table = namedTableReference?.SchemaObject.BaseIdentifier?.Value;
if (!string.IsNullOrWhiteSpace(table) && !table.StartsWith("#"))
{
if (!list.ContainsKey(spname))
{
SPAudit ll = new SPAudit();
ll.DeleteTable.Add(table);
ll.Parameters.AddRange(parameters);
list.Add(spname, ll);
}
else
{
SPAudit ll = list[spname];
ll.DeleteTable.Add(table);
}
}
}
base.ExplicitVisit(node);
}
}
public class SPAudit
{
public HashSet<string> InsertTable { get; set; }
public HashSet<string> UpdateTable { get; set; }
public HashSet<string> DeleteTable { get; set; }
public List<SPParam> Parameters { get; set; }
public SPAudit()
{
InsertTable = new HashSet<string>();
UpdateTable = new HashSet<string>();
DeleteTable = new HashSet<string>();
Parameters = new List<SPParam>();
}
}
public class SPParam
{
public string Name { get; set; }
public string DefaultValue { get; set; }
public string DataType { get; set; }
}
The SMO model exposes elements of the syntax tree. So instead of assuming a token by position, as in
UpdateSpecification?.Children?.FirstOrDefault();
look up the corresponding property in the documentation. For the update clause, the target table (or updatable view) can occur in different positions. Take this syntax:
UPDATE tablename SET column=value WHERE conditions
which is represented as
var targettable = ins?.UpdateSpecification?.Target?.ScriptTokenStream?.FirstOrDefault()?.Text;
in the SMO model. Whereas, a syntax unique to tsql,
UPDATE t SET t.columnname=value FROM tablename t WHERE conditions
will have its list of tables in the FROM clause.
Regarding the other two DML statements you mentioned: DELETE is the same because they share a common base class, DeleteInsertSpecification (Target).
For INSERT, there is the Target as well, and if its InsertSource is of type SelectInsertSource, this may be based on any number of tables and views too.
You can use following SQL Query:
SELECT *
FROM sys.dm_sql_referenced_entities ('dbo.APSP_MySP', 'OBJECT');
It gives you all the tables, views, SPs impacted in the stored procedure.
is_selected or is_select_all are set to 1 for selected references
is_updated is set to 1 for updated references
As query is reading from pre-defined system tables, it runs fast
If you need information about the referred object use the referenced_id column value to find details
You can use it in 2 ways:
Call the above query in parallel for each stored procedure
Create another query/SP which will loop and run it for every stored procedure
Change Proc_1 to your procedure name
Refine PATINDEX matching to cater for the different possibilites
Modify to look at all procedures
Does not cater for tables in dynamic sql or passed as parameters
Look out for any issues with dm_sql_referenced_entities
SELECT
e.TableName,
p.name,
PATINDEX('%DELETE '+e.TableName+'%', p.definition) AS is_delete,
PATINDEX('%INSERT INTO '+e.TableName+'%', p.definition) AS is_insert,
PATINDEX('%UPDATE '+e.TableName+'%', p.definition) AS is_update
FROM
(
SELECT distinct referenced_entity_name AS TableName
FROM sys.dm_sql_referenced_entities ('dbo.Proc_1', 'OBJECT')
) e,
(
SELECT o.name, m.object_id, definition
FROM sys.objects o, sys.sql_modules m
WHERE o.name = 'Proc_1'
AND o.type='P'
AND m.object_id = o.object_id
) p
I would recommend you querying the syscomments SQL view. The performance will be much better.
select text from sys.syscomments where text like '%DELETE%'
You can work with the results in the SQL Query or fetch all the results and filter the data in C#.
I have a list of Teachers and I would like to be able to display all data from the list of a specific teacher. I would like to search by name. However, either my list stays empty or I could not get the data from it. I do not know where the problem is.
Here is how i load the data from my sql server database to my list:
public void connectDbRead(List<Teacher> Teachers)
{
var teacherData = TeacherData.GetInstance();
//Get all students in the singleton
var teachers = teacherData.Teachers;
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = "Server=DESKTOP;Database=Test;Trusted_Connection=true";
conn.Open();
SqlCommand command = new SqlCommand("SELECT * FROM TEACHERS", conn);
command.Parameters.Add(new SqlParameter("0", 1));
teachers.Clear();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
teachers.Add(new Teacher
{
Name = (string)reader["NAME"],
FamilyName = (string)reader["FAMILY_NAME"],
Age = (int)reader["AGE"]
});
Console.WriteLine(String.Format("{0} | {1}| {2}",
reader[1], reader[2], reader[3]));
}
}
}
}
Here is how I search the data from the list:
public void searchTeacher(List<Teacher> Teachers)
{
string teacherName = "";
Console.WriteLine("Who do you want to find. Write his name: ");
teacherName = Console.ReadLine();
List<Teacher> teachers = Teachers.FindAll(x => x.Name == teacherName);
Console.WriteLine("List Of ELements!");
foreach (Teacher t in teachers)
{
Console.WriteLine(t.ToString());
}
}
I call it in the main function like that, but in switch cases:
var teacherData = TeacherData.GetInstance();
var teachers = teacherData.Teachers;
teacherData.searchTeacher(teachers);
teacherData.connectDbRead(teachers);
One line solution(don't even need to use LINQ) :
foreach(teachers t in Teacher)
if (t.Name == "TeacherName or any searcj query")
MessageBox.Show(t.name & t.age & .......)
Or if you still want to use LINQ :
forech(Teachers t in Teacher)
var result = Teachers.Where(Teacher => t.Name == "Name Here")
/// use the result as u want )
I changed things around a bit; deleted some things that I didn't understand but I tested it this way and it worked.
class Program
{
static List<Teacher> teachers = new List<Teacher>();
static void Main(string[] args)
{
connectDbRead();
searchTeacher();
Console.ReadLine();
}
public static void connectDbRead()
{
using (SqlConnection conn = new SqlConnection("Server=DESKTOP;Database=Test;Trusted_Connection=true"))
{
conn.Open();
SqlCommand command = new SqlCommand("SELECT * FROM TEACHERS", conn);
teachers.Clear();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
teachers.Add(new Teacher
{
Name = (string)reader["NAME"],
FamilyName = (string)reader["FAMILY_NAME"],
Age = (int)reader["AGE"]
});
}
}
}
}
public static void searchTeacher()
{
string teacherName = "";
Console.WriteLine("Who do you want to find. Write his name: ");
teacherName = Console.ReadLine();
var foundTeachers = teachers.FindAll(x => x.Name == teacherName);
Console.WriteLine("List Of ELements!");
foreach (Teacher t in foundTeachers)
{
Console.WriteLine(String.Format("{0} | {1} | {2}", t.Name, t.FamilyName, t.Age));
}
}
}
public class Teacher
{
public int Age { get; set; }
public string Name { get; set; }
public string FamilyName { get; set; }
}
I just downloaded ObjectListView, and have an issue with populating it.
I got list of MyObject:
public class MyObject
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public int Data { get; set; }
public MyObject(int id, int parentId, string name, int data)
{
Id = id;
ParentId = parentId;
Name = name;
Data = data;
}
}
List<MyObject> list = List<MyObject>();
I need to populate a TreeListView with MyObject elements (Using TreeListView).
Also I need one column been filled with .Data property.
I can not populate it even as a list(all items on the same level) and without any columns, I've tried this:
this.myTreeListView.SetObjects(list);
and this:
this.myTreeListView.Roots = list;
But the tree is still empty, nothing has been populated, what am I doing wrong ? Please help.
You can find some useful "getting started" information regarding the TreeListView here. Make sure you understand and use that concept.
However, there is no mention that you also have to add at least one column (you can do this in the designer). So this might be your problem. The TreeListView tutorial assumes that you already know how to use the ObjectListView.
I suggest you also read the general getting started guide, especially the "mental gear shift" section.
The crucial part of using an ObjectListView is configuring it. Most of this configuration can be done within the IDE by setting properties on the ObjectListView itself or on the columns that are used within the list. Some configuration cannot be done through properties: these more complex configurations are done by installing delegates (more on this later). Once the columns and control are configured, putting it into action is simple.
Hope this helps.
this way i do it. here i am giving my full code. have a look and ask me if u have any confusion. thanks
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form3 : Form
{
private List<Node> data;
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
InitializeData();
FillTree();
}
private void InitializeData()
{
string connString = "Data Source=xxx.xx.xx.xx\\test;Initial Catalog=Test;User id=sa;Password=test;";
string sql = "USP_RefundRequested";
SqlConnection conn = new SqlConnection(connString);
data = new List<Node>();
try
{
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand(sql, conn);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = ds.Tables[0];
if (ds != null)
{
if (ds.Tables.Count > 0)
{
ds.Relations.Add("ParentChild",ds.Tables[0].Columns["JID"],
ds.Tables[1].Columns["CID"]);
DataRelation orderRelation = ds.Relations["ParentChild"];
foreach (DataRow order in ds.Tables[0].Rows)
{
//Console.WriteLine("Subtotals for Order {0}:", order["OrderNumber"]);
Node parent1 = new Node( order["JID"].ToString(), "", "","","");
foreach (DataRow oChild in order.GetChildRows(orderRelation))
{
//Console.WriteLine("Order Line {0}: {1}", orderDetail["OrderLineNumber"], string.Format("{0:C}", orderDetail["Price"]));
parent1.Children.Add(new Node("", oChild["EntryDate"].ToString(),
oChild["RefundDate"].ToString(),
oChild["ActionBy"].ToString(),
oChild["Comments"].ToString()
));
}
data.Add(parent1);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex);
}
finally
{
conn.Close();
}
}
private void FillTree()
{
this.treeListView1.CanExpandGetter = delegate(object x) { return ((Node)x).Children.Count > 0; };
this.treeListView1.ChildrenGetter = delegate(object x) { return ((Node)x).Children; };
// create the tree columns and set the delegates to print the desired object proerty
BrightIdeasSoftware.OLVColumn JIDCol = new BrightIdeasSoftware.OLVColumn("Job ID", "JID");
JIDCol.AspectGetter = delegate(object x) { return ((Node)x).JID; };
BrightIdeasSoftware.OLVColumn EntryDatecol = new BrightIdeasSoftware.OLVColumn("Entry Date", "EntryDate");
EntryDatecol.AspectGetter = delegate(object x) { return ((Node)x).EntryDate; };
BrightIdeasSoftware.OLVColumn RefundDatecol = new BrightIdeasSoftware.OLVColumn("Refund Date", "RefundDate");
RefundDatecol.AspectGetter = delegate(object x) { return ((Node)x).RefundDate; };
BrightIdeasSoftware.OLVColumn ActionBycol2 = new BrightIdeasSoftware.OLVColumn("Action By", "ActionBy");
ActionBycol2.AspectGetter = delegate(object x) { return ((Node)x).ActionBy; };
BrightIdeasSoftware.OLVColumn Commentscol3 = new BrightIdeasSoftware.OLVColumn("Comments", "Comments");
Commentscol3.AspectGetter = delegate(object x) { return ((Node)x).Comments; };
// add the columns to the tree
this.treeListView1.Columns.Add(JIDCol);
this.treeListView1.Columns.Add(EntryDatecol);
this.treeListView1.Columns.Add(RefundDatecol);
this.treeListView1.Columns.Add(ActionBycol2);
this.treeListView1.Columns.Add(Commentscol3);
// set the tree roots
this.treeListView1.Roots = data;
treeListView1.Columns[1].Width = 142;
treeListView1.Columns[2].Width = 142;
treeListView1.Columns[3].Width = 179;
treeListView1.Columns[4].Width = 667;
treeListView1.Columns[treeListView1.Columns.Count - 1].Width = -2;
treeListView1.ExpandAll();
}
}
public class Node
{
public string _jid = "";
public string JID
{
get { return _jid; }
set { _jid = value; }
}
//public int _cid = 0;
//public int CID
//{
// get { return _cid; }
// set { _cid = value; }
//}
public string _entrydate;
public string EntryDate
{
get { return _entrydate; }
set { _entrydate = value; }
}
public string _refunddate;
public string RefundDate
{
get { return _refunddate; }
set { _refunddate = value; }
}
public string _actionby = "";
public string ActionBy
{
get { return _actionby; }
set { _actionby = value; }
}
public string _comments = "";
public string Comments
{
get { return _comments; }
set { _comments = value; }
}
public List<Node> _Children = null;
public List<Node> Children
{
get { return _Children; }
set { _Children = value; }
}
public Node(string JID, string EntryDate, string RefundDate, string ActionBy, string Comments)
{
this.JID = JID;
//this.CID = CID;
this.EntryDate = EntryDate;
this.RefundDate = RefundDate;
this.ActionBy = ActionBy;
this.Comments = Comments;
this.Children = new List<Node>();
}
}
}
ALTER PROC USP_RefundRequested
AS
BEGIN
;WITH Hierarchy AS
(
SELECT DISTINCT JID
,CAST(NULL AS DATETIME) EntryDate
,CAST(NULL AS DATETIME) RefundDate
,CAST(NULL AS VARCHAR(MAX)) Comments
,CAST(NULL AS BIT) Refund
,CAST(NULL AS VARCHAR(30)) ActionBy
,nLevel = 1
,0 AS CID
FROM refundrequested
UNION ALL
SELECT CAST(NULL AS INT) JID
,E.EntryDate
,E.RefundDate
,E.Comments
,E.Refund
,E.ActionBy
,H.nLevel+1
,H.JID AS CID
FROM refundrequested E
JOIN Hierarchy H ON E.JID = H.JID
)
--SELECT *
--FROM Hierarchy WHERE CID=0
--ORDER BY COALESCE(JID, CID) DESC, nLevel
SELECT * into #tmpHierarchy FROM Hierarchy
SELECT JID,EntryDate,RefundDate,ActionBy,Comments,CID
FROM tmpHierarchy WHERE CID=0
ORDER BY COALESCE(JID, CID) DESC, nLevel
SELECT JID,EntryDate,RefundDate,ActionBy,Comments,CID
FROM tmpHierarchy WHERE CID>0
ORDER BY COALESCE(JID, CID) DESC, nLevel
drop table #tmpHierarchy
END
go