Result Set Stored on Models - C# .NET 2.0 - c#

I have a function that gets the data in the database. Below are the code.
public DataTable getAllTransaction(OleDbConnection conn)
{
OleDbDataAdapter oleAdapter = new OleDbDataAdapter();
string query = "";
DataTable tblResult = new DataTable();
query = #"SELECT t.id AS `Transaction ID`,
c.id AS `Client ID`,
c.clientname AS `Client Name`,
t.cashvalue AS `Cash Value`,
t.amount AS `Amount`,
t.transdate AS `Transaction Date`,
t.remarks AS `Remarks`
FROM client AS c
INNER JOIN `transaction` AS t
ON c.id=t.clientid";
oleAdapter.SelectCommand = new OleDbCommand(query, conn);
oleAdapter.Fill(tblResult);
return tblResult;
}
My problem is, how could I store the result set into model (e.g. I don't want to return DataTable). Below is my Model Class.
Class TransactionModel
{
public int transID { get; set; }
public int clientID { get; set; }
public string clientName { get; set; }
public double cashValue { get; set; }
public double amout { get; set; }
public DateTime transDate { get; set; }
public string remarks { get; set; }
}

You could use LINQ and do:
var tranModel = from r in tblResult.Tables[0]
select new TransactionModel
{
transId = r.Field<int>("transID"),
clientId = r.Field<int>("clientId"),
clientName = r.Field<string>("ClientName")
}
Note since you are using .NET 2.0. LINQ is not directly available. You will have to use
Something like LINQBridge: http://www.albahari.com/nutshell/linqbridge.aspx
Another alternative is to loop through all of the rows in tblResult and have a generic list of TransactionModel. For instance:
List<TransactionModel> tModels = new List<TransactionModel>();
foreach (var row in tblResult.Tables[0].Rows)
{
tModels.Add(new TransactionModel
{
transId = row["TransId"],
clientId = row["ClientId"],
clientName = row["clientName"]
});
}

Because LINQ isn't available in .NET 2, you'd have to loop through the items yourself and transform them into your type. Something like this:
DataTable transactions = getAllTransactions();
List<TransactionModel> model = new List<TransactionModel>();
foreach (DataRow transaction in transactions.Rows)
{
TransactionModel tran = new TransactionModel
{
transId = transaction.Field<int>("transID"),
clientId = transaction.Field<int>("clientId"),
clientName = transaction.Field<string>("ClientName")
//etc...
};
model.Add(tran);
}

Do something like:
List<TransactionModel> TransactionItems = tblResult.AsEnumerable().Select(r =>
new TransactionModel
{
transID = r.Field<int>("TransactionID"),
clientID = r.Field<int>("clientID"),
and so on.....
}).ToList();
return items;

Related

Add new column headers and data to csv file from sql query c#

I'm in the middle of creating a console application in C# which extracts data from a few separate sql queries and displays the data in a csv file.
The column headers come from the file ExtractDocument.cs in a public record:
public record ExtractDocument
{
[Name("ItemID")]
public Guid ItemId { get; set; }
[Name("ItemDetailID")]
public Guid ItenDetailId { get; set; }
public string? Number { get; set; }
public string? Title { get; set; }
public string? Status { get; set; }
[Name("Item Type")]
public string? ItemType { get; set; }
public int MajorRevisionNumber { get; set; }
public int MinorRevisionNumber { get; set; }
public int RevisionNumberOffset { get; set; }
public string? CreatedDate { get; set; }
public string? ReleaseDate { get; set; }
public string? WithdrawnDate { get; set; }
[Name("Process Owner")]
public string? ProcessOwner { get; set; }
public string? Reviewer { get; set; }
public string? Approver { get; set; }
public string? Author { get; set; }
[Name("Admin Owner")]
public string? AdminOwner { get; set; }
}
The csv file is then made up in the file RecordRespository.cs like so:
public class RecordRepository : IRecordRepository
{
private readonly string _connectionString;
public RecordRepository(string connectionString)
{
_connectionString = connectionString;
}
public List<ExtractDocument> GetExtractDocuments()
{
var items = GetExtractData();
return items.Select().Select(x => new ExtractDocument
{
ItemId = x.Field<Guid>("ItemId"),
ItenDetailId = x.Field<Guid>("ItemDetailId"),
Number = x.Field<string>("Number"),
Status = x.Field<string>("Status"),
ItemType = x.Field<string>("Item Type"),
MajorRevisionNumber = x.Field<int>("MajorRevisionNumber"),
MinorRevisionNumber = x.Field<int>("MinorRevisionNumber"),
RevisionNumberOffset = x.Field<int>("RevisionNumberOffset"),
CreatedDate = x.Field<DateTime?>("CreatedDate")?.ToString("dd/MM/yyyy HH:mm"),
ReleaseDate = x.Field<DateTime?>("Releasedate")?.ToString("dd/MM/yyyy HH:mm"),
WithdrawnDate = x.Field<DateTime?>("WithdrawnDate")?.ToString("dd/MM/yyyy HH:mm"),
ProcessOwner = x.Field<string>("Process Owner"),
Reviewer = x.Field<string>("Reviewer"),
Approver = x.Field<string>("Approver"),
Author = x.Field<string>("Author"),
AdminOwner = x.Field<string>("Admin Owner")
}).ToList();
}
private DataTable GetTable(string sql, SqlParameter[]? paras = null)
{
var dt = new DataTable();
using var cnn = new SqlConnection(_connectionString);
using var cmd = new SqlCommand(sql, cnn);
if (paras != null && paras.Length > 0)
{
cmd.Parameters.AddRange(paras);
}
var da = new SqlDataAdapter(cmd);
da.Fill(dt);
return dt;
}
public DataTable GetExtractData()
{
var itemsTable = new DataTable();
var roleHoldersTable = new DataTable();
var customPropertiesTable = new DataTable();
using var cnn = new SqlConnection(_connectionString);
AddDataToTable(ItemsQuery, cnn, itemsTable);
AddDataToTable(RoleHoldersQuery, cnn, roleHoldersTable);
AddDataToTable(CustomPropertiesQuery, cnn, customPropertiesTable);
var getProcessOwner = SetColumnData(itemsTable, roleHoldersTable, "Process Owner", "HolderTitle", GetDetailIdFilter("OwnershipRoleTitle", "Process Owner"));
var getReviewer = SetColumnData(getProcessOwner, roleHoldersTable, "Reviewer", "HolderTitle", GetDetailIdFilter("OwnershipRoleTitle", "Reviewer"));
var getApprover = SetColumnData(getReviewer, roleHoldersTable, "Approver", "HolderTitle", GetDetailIdFilter("OwnershipRoleTitle", "Approver"));
var getAuthor = SetColumnData(getApprover, roleHoldersTable, "Author", "HolderTitle", GetDetailIdFilter("OwnershipRoleTitle", "Author"));
var getAdminOwner = SetColumnData(getAuthor, roleHoldersTable, "Admin Owner", "HolderTitle", GetDetailIdFilter("OwnershipRoleTitle", "Admin Owner"));
return getAdminOwner;
}
private static DataTable AddDataToTable(string query, SqlConnection connection, DataTable tableToFill)
{
using var cmd = new SqlCommand(query, connection);
var adapter = new SqlDataAdapter(cmd);
adapter.Fill(tableToFill);
return tableToFill;
}
private static Func<DataRow, string> GetDetailIdFilter(string secondColumnName, string secondColumnCondition)
{
return row => string.Format("ItemDetailID='{0}' AND {1} = '{2}'", Convert.ToString(row["ItemDetailID"]), secondColumnName, secondColumnCondition);
}
private static DataTable SetColumnData(
DataTable targetTable, DataTable sourceTable,
string columnToCreate, string sourceColumn, Func<DataRow, string> rowFilter)
{
targetTable.Columns.Add(columnToCreate, typeof(string));
foreach (DataRow row in targetTable.Rows)
{
DataRow[] rowsTarget;
rowsTarget = sourceTable.Select(rowFilter(row));
if (rowsTarget !=null && rowsTarget.Length > 0)
{
var values = rowsTarget.Select(r => r[sourceColumn].ToString()).ToList();
row[columnToCreate] = string.Join(", ", values);
}
else
{
row[columnToCreate] = "";
LogMissingData(columnToCreate, row["Title"]?.ToString() ?? "", row["ItemId"].ToString() ?? "");
}
}
return targetTable;
}
private static void LogMissingData(string column, string rowTitle, string itemId)
{
ErrorLogging.ErrorList.Add(new ErrorLogging()
{
ErrorType = "Warning",
Relation = "Database - to do with column: " + column,
Message = $"Data not found for document with the title: {rowTitle} and the itemId: {itemId}"
});
}
private const string ItemsQuery = #"
SELECT
id.ItemId, id.ItemDetailID, id.Number, id.Title,
id.Status, I.Type AS 'Item Type', id.MajorRevisionNumber, id.MinorRevisionNumber,
RevisionNumberOffset = ISNULL(id.RevisionNumberOffset, 0), id.CreatedDate, id.ReleaseDate,
id.WithdrawnDate
FROM AgilityItemView v
JOIN ItemDetail id
ON id.ItemDetailID = v.ItemDetailId
JOIN Item i
on i.ItemID = v.ItemId";
private const string RoleHoldersQuery = #"
SELECT
ID.ItemID ,
ID.ItemDetailID,
OwnershipRoleTitle = IOR.Title,
HolderTitle = P.Title,
VersionRank = P.VersionRank
FROM
dbo.ItemDetailOwnershipRole IDOR
INNER JOIN ItemDetail ID
ON ID.ItemDetailID = IDOR.ItemDetailID
INNER JOIN dbo.ItemOwnershipRole IOR
ON IDOR.ItemOwnershipRoleID = IOR.ItemOwnershipRoleID
INNER JOIN dbo.ItemDetailOwnershipRoleHolder IDOH
ON IDOH.ItemDetailOwnershipRoleID = IDOR.ItemDetailOwnershipRoleID
INNER JOIN dbo.AgilityItemView P
ON IDOH.ItemOwnershipRoleHolderItemID = P.ItemID
WHERE IOR.Title IN ('Process Owner', 'Reviewer', 'Approver', 'Author', 'Admin Owner')";
private const string CustomPropertiesQuery = #"
SELECT id.ItemID,
id.ItemDetailID
, cp.Title, cpi.ItemTitle
FROM AgilityItemView v
JOIN ItemDetail id
ON id.ItemDetailID = v.ItemDetailId
JOIN CustomPropertyItemReference cpir
ON cpir.ItemDetailID = id.ItemDetailID
JOIN CustomPropertyItem cpi
ON cpi.CustomPropertyItemID = cpir.ReferenceItemID
JOIN CustomProperty cp
ON cp.CustomPropertyID = cpi.CustomPropertyID";
}
}
This works by creating a data table and then adding a new column with the new value in the row based on matching ItemDetailIds from the queries, if that makes sense?
The issue I'm having is I do not have access to the database this application will be running against so just having to use something else for the time being. What I have in the public record ExtractDocument are the column headers I know 100% will be there.
For the query:
private const string CustomPropertiesQuery = #"
SELECT id.ItemID,
id.ItemDetailID
, cp.Title, cpi.ItemTitle
FROM AgilityItemView v
JOIN ItemDetail id
ON id.ItemDetailID = v.ItemDetailId
JOIN CustomPropertyItemReference cpir
ON cpir.ItemDetailID = id.ItemDetailID
JOIN CustomPropertyItem cpi
ON cpi.CustomPropertyItemID = cpir.ReferenceItemID
JOIN CustomProperty cp
ON cp.CustomPropertyID = cpi.CustomPropertyID";
I need to add more column headers to the csv file based on the distinct values that come from "cp.Title", since I do not know what those values will be I have just been told to have the application grab each unique one rather than specify specific ones like I have done in the RoleHoldersQuery.
I have managed to do this by doing the following:
public List<string> GetADPTitles()
{
var customPropertiesTable = new DataTable();
using var cnn = new SqlConnection(_connectionString);
AddDataToTable(CustomPropertiesQuery, cnn, customPropertiesTable);
List<string>uniqueADPTitles = new List<string>();
foreach (DataRow dr in customPropertiesTable.Rows)
{
if (!uniqueADPTitles.Contains((string)dr["ADPTitle"]))
{
uniqueADPTitles.Add((string)dr["ADPTitle"]);
}
}
return uniqueADPTitles;
}
I have then also created a second method for getting the row values for the columns as well like so:
public List<string> ExtractADPData()
{
var customPropertiesTable = new DataTable();
using var cnn = new SqlConnection(_connectionString);
AddDataToTable(CustomPropertiesQuery, cnn, customPropertiesTable);
var items = GetExtractData();
var titles = GetADPTitles();
List<DataTable> ADPDataTables = new List<DataTable>();
foreach (var title in titles)
{
ADPDataTables.Add(SetColumnData(items, customPropertiesTable, title, "ItemTitle", GetDetailIdFilter("ADPTitle", title)));
}
List<string>test = new List<string>();
test.Add(ADPDataTables.ToList().ToString());
return test;
}
And then in my Runner.cs file (which calls all the method I do the following:
var extractData = repo.GetExtractDocuments();
ExportLog.SaveFile(exportFile, extractData);
Console.WriteLine(extractData.GetType());
List<string> records = repo.GetADPTitles().ToList();
List<string> adpData = repo.ExtractADPData();
foreach ( var record in records)
{
var filePath = exportFile;
var csv1 = File.ReadLines(filePath.ToString()).Select((line, index) => index == 0
? line + "," + record.ToString()
: line + "," + adpData.ToString()).ToList();
File.WriteAllLines(filePath.ToString(), csv1);
}
This kind of works, I get the new columns added to the csv file and the rows are generated but each row has a value of: System.Collections.Generic.List`1[System.String]
rather than the actual data itself. Where have I gone wrong and how can I get the actual value rather than what is currently getting displayed?

Feeding crystal report with filtered data c#

Im trying to pass a query as the DataSource for my crystal report. But rather than the report displaying the filtered data, it displays all the data in the associated tables.
This is what im doing to pass the data
Accessor
class cStockIssuanceSlipDetails
{
public string itemCode { get; set; }
public string itemDescription { get; set; }
public double unitcost { get; set; }
public int quantity { get; set; }
public double amount { get; set; }
}
Filter
public DataSet Products_info(int slip_no)
{
string queryProducts = "SELECT p.ItemCode,p.itemDescription,p.SaleCost,slip.Quantity,slip.Amount FROM tblstockissuanceslip slip " +
"INNER JOIN tblprowareinventory pi ON slip.inventoryID_FK = pi.inventoryID " +
"INNER JOIN tblprowareproducts p ON pi.ItemID_FK = p.ItemID "+
"WHERE slip.SIP_NO = ?slipno";
using (MySqlCommand cmd = new MySqlCommand(queryProducts,con.connection))
{
cmd.Parameters.AddWithValue("?slipno", slip_no);
DataSet ds = new DataSet();
using (MySqlDataAdapter mda = new MySqlDataAdapter(cmd))
{
mda.Fill(ds);
return ds;
}
}
}
Setting the DataSource
List<cStockIssuanceSlipDetails> _List = new List<cStockIssuanceSlipDetails>();
DataSet ds = Data.Products_info(5);
foreach (DataRow dr in ds.Tables[0].Rows)
{
_List.Add(new cStockIssuanceSlipDetails
{
itemCode = dr["itemCode"].ToString(),
itemDescription = dr["itemDescription"].ToString(),
unitcost = Convert.ToDouble(dr["SaleCost"]),
quantity = Convert.ToInt32(dr["Quantity"]),
amount = Convert.ToDouble(dr["Amount"]),
});
}
rStockIssuanceSlip1.SetDataSource(_List);
Can you try something like this?
class cStockIssuanceSlipDetails
{
public string itemCode { get; set; }
public string itemDescription { get; set; }
public double unitcost { get; set; }
public int quantity { get; set; }
public double amount { get; set; }
--Create a variable to store the value you want to pass in your sql statement
--use this variable to store the value before concatenating in to your sql statement
public string topass { get; set; }
}
Filter
public DataSet Products_info(int slip_no)
{
string queryProducts = "SELECT p.ItemCode,p.itemDescription,p.SaleCost,slip.Quantity,slip.Amount FROM tblstockissuanceslip slip " +
"INNER JOIN tblprowareinventory pi ON slip.inventoryID_FK = pi.inventoryID " +
"INNER JOIN tblprowareproducts p ON pi.ItemID_FK = p.ItemID "+
"WHERE slip.SIP_NO = ""+topass+";
using (MySqlCommand cmd = new MySqlCommand(queryProducts,con.connection))
{
--remove line below
cmd.Parameters.AddWithValue("?slipno", slip_no);
--remove line above
DataSet ds = new DataSet();
using (MySqlDataAdapter mda = new MySqlDataAdapter(cmd))
{
mda.Fill(ds);
return ds;
}
}
}
What really happens is, the parameter cannot retrieve the value which you are trying to pass. Just a tip, try learning how to use stored procedures and functions in SQL, they will make your life more peaceful.

Cannot read List<myClass> from a webservice

I have a webservice that returns a list.
[WebInvoke(Method = "POST", UriTemplate = "GetBatchList", RequestFormat = WebMessageFormat.Xml)]
public List<Batch> GetBatchList()
{
List<Batch> listBatches = null;
try
{
listBatches = api.GetBatchList();
}
catch
{
return null;
}
return listBatches;
}
where
public class Batch
{
public string BatchName { get; set; }
public List<MAASUsers> Users { get; set; }
}
public class MAASUsers
{
public string firstName { get; set; }
public string lastName { get; set; }
public string sourceEmail { get; set; }
public int sourceTenantID { get; set; }
public string targetEmail { get; set; }
public int targetTenantID { get; set; }
public string migrationStatus { get; set; }
}
In the client side of the application, I cannot manage to get the content correctly.
How can I consume the webservice respons.
I've attempted in vain this solution: datacontractserializer deserialize list<> always empty
I've also tried another solution below.
But, for both solutions I'm stuck retrieving the list : List Users
// Call the webservice, then read the respons
[...]
using (var response = request.GetResponse())
{
DataSet dsTable = new DataSet();
dsTable.ReadXml(response.GetResponseStream(), XmlReadMode.Auto);
if (dsTable.Tables.Count > 0)
{
table = dsTable.Tables[0];
}
}
if (table.Rows.Count > 0)
{
list = (from DataRow row in table.Rows
select new Batch
{
BatchName = row["BatchName"].ToString()
/////// But here how do I get List<MAASUsers> Users?
/////// the content is returned in dsTable.Tables[1]
/////// and I don't see any "joining key" ???
}).ToList();
}
Note that the webservice has correctly sent the content of List ( see datacontractserializer deserialize list<> always empty for sample XML returned)
There is a relation table. The dataset adds them automatically and add a "Class"_ID to each row that facilitates the relation between the tables.
See below how to use it.
using (var response = request.GetResponse())
{
DataSet dsTable = new DataSet();
dsTable.ReadXml(response.GetResponseStream(), XmlReadMode.Auto);
lstMaasBatches= (from DataRow row in dsTable.Tables[0].Rows
select new MAASBatch
{
BatchName = row["BatchName"].ToString(),
BatchId = Convert.ToInt32(row["MAASBatch_Id"].ToString())
}).ToList();
foreach (MAASBatch batch in lstMaasBatches)
{
int batchID = batch.BatchId;
List<MAASUsers> lst = (from DataRow row in dsTable.Tables[2].Rows
where row.Field<int>("Users_Id") == batchID
select new MAASUsers
{
ID = Convert.ToInt32(row["ID"].ToString()),
firstName = Convert.ToString(row["FirstName"].ToString()),
lastName = Convert.ToString(row["LastName"].ToString()),
migrationStatus = row["migrationStatus"].ToString(),
sourceEmail = Convert.ToString(row["SourceEmail"].ToString()),
sourceAgentID = Convert.ToInt32(row["sourceTenantID"].ToString()),
targetEmail = Convert.ToString(row["TargetEmail"].ToString()),
targetAgentID = Convert.ToInt32(row["targetTenantID"].ToString()),
}).ToList();
batch.Users = lst;
}
}
}

devexpress xtrareport binding multiple list datasource

I am attaching Class Detail as my DataSource to the report;
class Detail
{
public string Name { get; set; }
public string State { get; set; }
public string City { get; set;}
public List<Transaction> tran { get; set; }
}
class Transaction
{
public string TransactionDate { get; set; }
public string TransactionDescription { get; set; }
}
and in my query i send it as List.
public List GetAccount(string account) {
List detail = new List();
sql ....
foreach (DataRow dr in dt.Rows)
{
detail.Add(new Detail()
{
Name= dr["name"].Equals(DBNull.Value) ? string.Empty : dr["name"].ToString(),
.....
tran = GetTransactionDetail(account)// calling a list
});
}
return detail;
}
public List<Transaction> GetTransactionDetail(string account)
{
....
}
and at the Form1.cs
XtraReport1 rep = new XtraReport1();
printControl1.PrintingSystem = rep.PrintingSystem;
var ls = query.GetAccount(accountNo);
rep.DataSource = ls;
rep.CreateDocument();
in the report i should get a list of transaction details but i get only the first row.
thanks,
It depends how your report is designed. Usually you need a separate band (DetailReport) for all of the details to be visible (if you're using XRTable).
Sir you should use DataSet and query.GetAccount(accountNo) returns DataTable
Then try like this. It works for me.
XtraReport1 rep = new XtraReport1();
printControl1.PrintingSystem = rep.PrintingSystem;
var ds = new ds("TestDataSet");
var ls = query.GetAccount(accountNo);
ds.Tables.Add(ls);
rep.DataSource = ds;
rep.DataMember = ls.TableName;
rep.CreateDocument();

initialize the proprty of a class, which is of another type, by extension method and object initializers

.
.
List<DailyEntry> entries = null;
using (SqlCeDataReader rdr = cmd.ExecuteReader())
{
entries = rdr.Select(r => new DailyEntry
{
ID = int.Parse(r["Col_ID"].ToString()),
Amount = decimal.Parse(r["Col_Amount"].ToString()),
Date = DateTime.Parse(r["Col_Date"].ToString()),
Remarks = r["Col_Remarks"].ToString()
}).ToList();
}
.
.
extrension method select is
public static IEnumerable<T> Select<T>(this SqlCeDataReader reader,
Func<SqlCeDataReader, T> projection)
{
while (reader.Read())
{
yield return projection(reader);
}
}
where DailyEntry class is
class DailyEntry
{
public int ID { get; set; }
public DateTime Date { get;set; }
public Site Site { get; set; }
public decimal Amount { get; set; }
public string Remarks { get; set; }
}
DailyEntry class has one more property of type Site
class Site
{
public int SiteID { get; set; }
public string SiteName { get; set; }
}
Now I want to initialize the Site property of DailyEntry just how all other properties are set in first code snippet..
I am not finding the way?
Unless I didn't understand the question, the answer is:
List<DailyEntry> entries = null;
using (SqlCeDataReader rdr = cmd.ExecuteReader())
{
entries = rdr.Select(r => new DailyEntry
{
ID = int.Parse(r["Col_ID"].ToString()),
Amount = decimal.Parse(r["Col_Amount"].ToString()),
Date = DateTime.Parse(r["Col_Date"].ToString()),
Remarks = r["Col_Remarks"].ToString(),
Site = new Site
{
SiteID = int.Parse(r["Site_ID"].ToString()),
SiteName = r["name"].ToString()
}
}).ToList();
}
Why not use the existing func?
Something like this:
entries = rdr.Select(r => new DailyEntry
{
ID = int.Parse(r["Col_ID"].ToString()),
Amount = decimal.Parse(r["Col_Amount"].ToString()),
Date = DateTime.Parse(r["Col_Date"].ToString()),
Remarks = r["Col_Remarks"].ToString(),
Site = new SiteĀ {SideID = r["..."], SiteName = r["..."]}
}).ToList();
All you have to do is create it inline the same way you are creating your new DailyEntry instance:
rdr.Select(r => new DailyEntry
{
ID = int.Parse(r["Col_ID"].ToString()),
Amount = decimal.Parse(r["Col_Amount"].ToString()),
Date = DateTime.Parse(r["Col_Date"].ToString()),
Remarks = r["Col_Remarks"].ToString(),
Site = new Site
{
SiteID = int.Parse(r["Site_ID"].ToString()),
SiteName = r["Site_Name"].ToString()
}
}

Categories

Resources