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();
Related
I have three classes
public class FeatureBook
{
public string Id { get; set; }
public String name { get; set; }
public String type { get; set; }
}
public class Feature
{
public String feature_id { get; set; }
public String value { get; set; }
}
public class Human {
public string Id { get; set; }
public bool validated { get; set; }
public List<Feature> features { get; set; }
public override String ToString() => Id;
}
Human has List<Feature>. Feature is linked to FeatureBook by feature_id
And I have DataGridView.
How can I get something like in the picture:
First of all, for such of functionality, i'd use 2 datagridviews with master-detail relationship.
Second of all, if you would like to bind data to single datagridview, you need to convert Feature's rows into columns. Here is complete sample (created with LinqPad):
void Main()
{
//create human list
List<Human> people = new List<Human>()
{
new Human(){Id = "H1", validated =false, features = new List<Feature>()
{
new Feature(){feature_id = "H1F1", value ="Feature 1"},
new Feature(){feature_id = "H1F2", value ="Feature 2"}
}},
new Human(){Id = "H2", validated =false, features = new List<Feature>()
{
new Feature(){feature_id = "H2F1", value ="Feature 1"},
new Feature(){feature_id = "H2F2", value ="Feature 2"},
new Feature(){feature_id = "H2F3", value ="Feature 3"},
new Feature(){feature_id = "H2F4", value ="Feature 4"},
new Feature(){feature_id = "H2F5", value ="Feature 5"}
}}
};
//create datatable
DataTable dt = new DataTable();
//add known columns (related to Human)
dt.Columns.AddRange(new DataColumn[]
{
new DataColumn("Id", typeof(string)),
new DataColumn("validated", typeof(string))
});
//get max. of futures
int fc = people.Select(x=>x.features.Count).Max();
//add columns related to Feature
for(int i=0; i<fc; i++)
dt.Columns.Add(new DataColumn($"Feature {i}"));
//add data to datatable
foreach(Human h in people)
{
//add Human details
DataRow dr = dt.NewRow();
dr["Id"] = h.Id;
dr["validated"] = h.validated;
//add Feature details
for(int i=0; i<h.features.Count; i++)
{
Feature f = h.features[i];
dr[$"Feature {i}"] = f.value;
}
dt.Rows.Add(dr);
}
//datatable is ready to use
//dump its content ;)
dt.Dump();
}
// Define other methods and classes here
public class FeatureBook
{
public string Id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class Feature
{
public string feature_id { get; set; }
public string value { get; set; }
}
public class Human
{
public string Id { get; set; }
public bool validated { get; set; }
public List<Feature> features { get; set; }
public override string ToString() => Id;
}
Note: there's few other ways to achieve that, but i wanted to show you the simplest way ;)
I created a simple RESTful application in WCF(c#). When I'm populating using (GET) I've received this error
"Object reference not set to an instance of an object".
I received the error in the part of target.DocumentLines[0].itemCode = "";.
Here's my code:
public PRRequestData[] getAllPR()
{
List<PRRequestData> list = new List<PRRequestData>();
try
{
string sqlSelect = "SELECT DocEntry, Comments, ReqDate FROM OPRQ";
APP.strCommand = sqlSelect;
DataTable dt = new DataTable();
dt = APP.Ds.Tables[0];
foreach (DataRow row in dt.Rows)
{
// Person target = Activator.CreateInstance();
PRRequestData target = new PRRequestData();
target.requiredDate = row["ReqDate"].ToString();
target.remarks = row["Comments"].ToString();
target.docEntry = row["DocEntry"].ToString();
// DataColumnAttribute.Bind(row,target);
sqlSelect = "SELECT ItemCode, Quantity, Price, VendorNum, TaxCode FROM PRQ1 WHERE DocEntry = '" + row["DocEntry"].ToString() + "' ";
APP.strCommand = sqlSelect;
for (var i = 0; i < APP.Ds.Tables[0].Rows.Count; i++)
{
target.DocumentLines[0].itemCode = "";
}
list.Add(target);
}
return list.ToArray();
}
catch (Exception e)
{
e.ToString();
}
return list.ToArray();
Here's my DataContract source code also:
[DataContract(Namespace = "")]
public class PRRequestData
{
[DataMember]
public string docEntry { get; set; }
[DataMember]
public string remarks { get; set; }
[DataMember]
public string requiredDate { get; set; }
//[DataMember]
//public int rowcount { get; set; }
[DataMember]
public RequestDataDetails[] DocumentLines;
}
[DataContract]
public class RequestDataDetails
{
[DataMember]
public string itemCode { get; set; }
[DataMember]
public decimal quantity { get; set; }
[DataMember]
public decimal price { get; set; }
[DataMember]
public string supplier { get; set; }
[DataMember]
public string taxcode { get; set; }
}
Looks like you're not initialising this property
[DataMember]
public RequestDataDetails[] DocumentLines;
I recommend you to use List instead of RequestDataDetails[], as anyway you'll have to use an internal list.
Initialise the List of RequestDataDetails to fill it from the query, before the for loop.
List<RequestDataDetails> requestDetails = new List<RequestDataDetails>
Then change the for loop to add to that list instead of setting an array, im using the assignment you were doing, not sure if it'll do what you expect, just tell me if it suits your needs.
requestDetails.add(new RequestDataDetails { itemCode = "" });
instead of
target.DocumentLines[0].itemCode = "";
Then after the for loop convert the list to an array and assign it to target
target.DocumentLines = requestDetails.ToArray();
Hope it works!
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;
}
}
}
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;
.
.
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()
}
}