This is my code
public List<InvoiceJoin> ShowIvoiceList()
{
InvoiceJoin ij = new InvoiceJoin();
List<InvoiceJoin> list;
var data = (from t in _Entity.TblInvoices join t0 in _Entity.TblClients on new { ReceiverCode = t.ReceiverCode } equals new { ReceiverCode = t0.ClientCode }
select new
{
t.RakeNumber,
t.ReceiverCode,
t.ConsigneeCode,
t.InvoiceNumber,
t.InvoiceDate,
t.RecordStatus,
t0.ClientCode,
t0.ClientDescription,
t0.ClientAddress1,
t0.ClientAddress2,
t0.ClientAddress3,
t0.ClientCity,
t0.ClientState,
t0.ClientCountry,
t0.ClientZipCode,
}).ToList();
foreach (var item in data)
{
list.Add(item);
}
return list;
}
my invoicejoin class
public class InvoiceJoin
{
public TblInvoice invoice { get; set; }
public string Cdetails { get; set; }
public string Cname { get; set; }
public string Caddr { get; set; }
public string Pname { get; set; }
public string Paddr { get; set; }
}
Its not working
I need to show two sql table data list in single view how i can do this in linq pls some ne help friends i need to show in html table. . .
make sure that you have class InvoiceJoin with constructor which take 2 parameters: invoice and client
class InvoiceJoin
{
private TblInvoice invoice;
private TblClient client;
public InvoiceJoin(TblInvoice invoice,TblClient client)
{
this.invoice=invoice;
this.client=client;
//...
}
public string RakeNumber{ get{return invoice.RakeNumber} set{invoice.RakeNumber=value;}}
//... ather invoice properties you want to see in grid
public string ClientCode{ get{return client.ClientCode} set{client.ClientCode=value;}}
// ...ather clientproperties you want to see in grid
}
loading data:
List<InvoiceJoin> data = (from invoice in db.TblInvoices
join client in db.TblClients
on invoice.ReceiverCode equals client.client
select new{Invoice=invoice,Client=client}).ToList()
.Select(n=>new InvoiceJoin(n.Invoice,n.Client)).ToList()
Use the LINQ Union method like this:
var data = (from t in _Entity.TblInvoices
join t0 in _Entity.TblClients on new { ReceiverCode = t.ReceiverCode } equals new { ReceiverCode = t0.ClientCode }
select new
{
t.RakeNumber,
t.ReceiverCode,
t.ConsigneeCode,
t.InvoiceNumber,
t.InvoiceDate,
t.RecordStatus,
t0.ClientCode,
t0.ClientDescription,
t0.ClientAddress1,
t0.ClientAddress2,
t0.ClientAddress3,
t0.ClientCity,
t0.ClientState,
t0.ClientCountry,
t0.ClientZipCode,
}).Union( // 2nd linq query with same result set as first here);
Related
I have this code:
public class Customer
{
Int32 id { get; set; } = 0;
User user1 { get; set; } = null;
User user2 { get; set; } = null;
}
/* ... */
using (MySqlConnection conn = new MySqlConnection(Costanti.connessione))
{
conn.Open();
MySqlCommand m = new MySqlCommand("
SELECT c1.*, u1.*, u2.*
FROM customers as c1
inner join utenti u1 on u1.customer_id = c1.id
inner join utenti u2 on u2.customer_id = c1.id
", conn);
MySqlDataReader x = m.ExecuteReader();
DataTable dataTable = new DataTable();
dataTable.Load(x);
String json_string = Newtonsoft.Json.JsonConvert.SerializeObject(dataTable);
List<Customer> lista = new List<Customer>();
Newtonsoft.Json.JsonConvert.PopulateObject(json_string, lista);
conn.Close();
}
How could I map c1.* fields of select to a generic Customer customer_1, and then u1.* and u2.* into customer_1's properties? Newtonsoft.Json.JsonConvert.PopulateObject doesn't let me do it.
The intermediate json_string looks like:
[
{
"id":1,
"id_user":8,
"name":"manuel",
"id_user1":2,
"name1":"michael"
},
{
"id":2,
"id_user":3,
"name":"friedrich",
"id_user1":6,
"name1":"antony"
}
]
And the result has to be a list composed by:
Customer(with id=1), with User1(8,"manuel") and User2(2,"michael");
Customer(with id=2), with User1(3,"friedrich") and User2(6,"antony").
The main reason your call to PopulateObject() is not working is that your c# data model does not match the schema of your JSON. If I use one of the tools from How to auto-generate a C# class file from a JSON object string to auto-generate a data model from your JSON, I get:
public class RootObject
{
public int id { get; set; }
public int id_user { get; set; }
public string name { get; set; }
public int id_user1 { get; set; }
public string name1 { get; set; }
}
This looks nothing like your Customer class.
The secondary reason that PopulateObject() fails is that Json.NET will only populate public members by default -- and yours are all private.
To fix this, I might suggest skipping the DataTable and json_string representations entirely, and building your list directly from the IDataReader interface that MySqlDataReader implements:
var lista = x
.SelectRows(r =>
// Extract the row data by name into a flat object
new
{
id = Convert.ToInt32(r["id"], NumberFormatInfo.InvariantInfo),
id_user = Convert.ToInt32(r["id_user"], NumberFormatInfo.InvariantInfo),
name = r["name"].ToString(),
id_user1 = Convert.ToInt32(r["id_user1"], NumberFormatInfo.InvariantInfo),
name1 = r["name1"].ToString(),
})
.Select(r =>
// Convert the flat object to a `Customer`.
new Customer
{
id = r.id,
user1 = new User { Id = r.id_user, Name = r.name },
user2 = new User { Id = r.id_user1, Name = r.name1 },
})
.ToList();
Using the extension method:
public static class DataReaderExtensions
{
// Adapted from this answer https://stackoverflow.com/a/1202973
// To https://stackoverflow.com/questions/1202935/convert-rows-from-a-data-reader-into-typed-results
// By https://stackoverflow.com/users/3043/joel-coehoorn
public static IEnumerable<T> SelectRows<T>(this IDataReader reader, Func<IDataRecord, T> select)
{
while (reader.Read())
{
yield return select(reader);
}
}
}
This assumes that your Customer data model now looks like:
public class Customer
{
public Int32 id { get; set; }
public User user1 { get; set; }
public User user2 { get; set; }
}
public class User
{
public Int32 Id { get; set; }
public string Name { get; set; }
}
You could also combine the SelectRows and Select calls into a single method; I separated them for clarity. Skipping the DataTable and JSON representations should be simpler and more performant than your current approach.
Demo fiddle using a mockup data reader here.
I have a sequence of objects, whose type has many properties and I would like to join it with another sequence and set a value taking from the second sequence. But because there are many properties I do not prefer to create a new anonymous type by doing all those property assignments. Is there a better way to do this in a single linq query (having been trying un-successfully with let)
var x = from lt in legalTerms
join le in legalEntities on lt.LegalEntityCode equals le.Code
select new {a = lt.a, b = lt.b, c = le.c, d = lt.d .... z=lt.z} // don't like
I need a sequence like legalTerms where the items have that one property updated from legalEntities
Wish there was somehow a way to clone le and set that one property c = le.c without using reflection etc
Basically this is what I wonder is possible in a linq statement
foreach (var lt in legalTerms)
{
foreach (var le in legalEntities)
{
if (le.Code == lt.LegalEntityCode)
{
lt.LegalEntity = le.Name;
}
}
}
how about this
var map = new Func<LegalTerm, LegalEntity, LegalTerm>((term, entity) =>
{
term.LegalEntity = entity.Name;
return term;
});
var query = from lt in legalTerms
join le in legalEntities
on lt.Code equals le.LegalEntityCode
select map(lt, le);
knowing that you have some sort of structures similar to those bellow
public class LegalTerm
{
public string Code { get; set; }
public string LegalEntity { get; set; }
public string a { get; set; }
public string b { get; set; }
public string c { get; set; }
public string d { get; set; }
}
public class LegalEntity
{
public string LegalEntityCode { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
This really has me stumped. I have four tables in the database, and unfortunately the person who designed this table didn't create referential constraints. So, there is no navigation properties available.
Four tables are:
CiscoPhoneReport
ApplicationSummary
CSQActivityReport
CallDistributionSummary
The idea is that for each PhoneReportID in CiscoPhoneReport, there is one ApplicationSummary, three CSQActivityReport, and three CallDistributionSummary.
I want the output as below in JSON format:
`[{
"appSummary":{
"startDate":"2015-09-01T00:00:00",
"endDate":"2015-09-30T00:00:00",
"applicationName":"RationalDrugTherapy",
"callsPresented":14504,
"callsAbandoned":1992,
"callsHandled":12512
},
"csqModel":[
{
"startDate":null,
"csqid":"3",
"callsPresented":6271,
"avgQueueTime":"00:00:21",
"callsHandled":0,
"avgAnswerSpeed":"00:00:00",
"avgHandleTime":"00:02:08",
"callsHandledGreaterThan3t":5742,
"callsAbandoned":99,
"avgAbandonTime":"00:02:20",
"maxQueueTime":"00:25:26",
"maxHandleTime":"00:19:33",
"maxAbandonTime":"00:17:50"
},{
"startDate":null,
"csqid":"3",
"callsPresented":6271,
"avgQueueTime":"00:00:21",
"callsHandled":0,
"avgAnswerSpeed":"00:00:00",
"avgHandleTime":"00:02:08",
"callsHandledGreaterThan3t":1728,
"callsAbandoned":99,
"avgAbandonTime":"00:02:20",
"maxQueueTime":"00:25:26",
"maxHandleTime":"00:19:33",
"maxAbandonTime":"00:17:50"
}, {
"startDate":null,
"csqid":"3",
"callsPresented":6271,
"avgQueueTime":"00:00:21",
"callsHandled":0,
"avgAnswerSpeed":"00:00:00",
"avgHandleTime":"00:02:08",
"callsHandledGreaterThan3t":3363,
"callsAbandoned":99,
"avgAbandonTime":"00:02:20",
"maxQueueTime":"00:25:26",
"maxHandleTime":"00:19:33",
"maxAbandonTime":"00:17:50"
}]
}]`
For this, I created DTO:
`public class AppSummary
{
public string PhoneReportID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string ApplicationName { get; set; }
public int CallsPresented { get; set; }
public int CallsAbandoned { get; set; }
public int CallsHandled { get; set; }
}
`
`public class CSQModel
{
public string StartDate { get; set; }
public string CSQID { get; set; }
public int CallsPresented { get; set; }
public TimeSpan AvgQueueTime { get; set; }
public int CallsHandled { get; set; }
public TimeSpan AvgAnswerSpeed { get; set; }
public TimeSpan AvgHandleTime { get; set; }
public int CallsHandledGreaterThan3t { get; set; }
public int CallsAbandoned { get; set; }
public TimeSpan AvgAbandonTime { get; set; }
public TimeSpan MaxQueueTime { get; set; }
public TimeSpan MaxHandleTime { get; set; }
public TimeSpan MaxAbandonTime { get; set; }
}
`
`public class PhoneReport
{
public AppSummary AppSummary { get; set; }
//Initially, I had it like this
public CSQModel CSQModel { get; set; }
//I renamed the property as LIST to see if I could use it and add data to the list in linq, but I couldn't use the list within select expression in linq.
//public List<CSQModel> CSQModel { get; set; }
}
`
The CSQModel class has needed data from both CSQActivityReport and CallDistributionSummary tables.
I was able to create a linq statement with table joins as below.
var res = from cpr in db.CiscoPhoneReport
join app in db.ApplicationSummary on cpr.PhoneReportID equals app.PhoneReportID into g1
from appGroup in g1.DefaultIfEmpty()
join csq in db.CSQActivityReport on cpr.PhoneReportID equals csq.PhoneReportID into g2
from csqGroup in g2.DefaultIfEmpty()
join call in db.CallDistributionSummary on cpr.PhoneReportID equals call.PhoneReportID into g3
from callGroup in g3.DefaultIfEmpty()
where cpr.PhoneReportID == phoneReportID
select new PhoneReport
{
AppSummary = new AppSummary
{
StartDate = cpr.StartDate,
EndDate = cpr.EndDate,
ApplicationName = appGroup.ApplicationName,
CallsPresented = appGroup.CallsPresented,
CallsAbandoned = appGroup.CallsAbandoned,
CallsHandled = appGroup.CallsHandled
},
CSQModel = new CSQModel
{
CSQID = csqGroup.CSQID.ToString(),
CallsPresented = csqGroup.CallsPresented,
AvgQueueTime = csqGroup.AvgQueueTime,
AvgHandleTime = csqGroup.AvgHandleTime,
CallsHandledGreaterThan3t = callGroup.CallsHandledGreaterThan3t,
CallsAbandoned = csqGroup.CallsAbandoned,
AvgAbandonTime = csqGroup.AvgAbandonTime,
MaxQueueTime = csqGroup.MaxQueueTime,
MaxHandleTime = csqGroup.MaxHandleTime,
MaxAbandonTime = csqGroup.MaxAbandonTime
}
};
`
The result I'm getting is a set of data with 9 rows, which makes sense - as in inner join in SQL. But this is not what I wanted.
How can I obtain the data as in the JSON format above? I couldn't figure it out at all.
I think part of the reason you are seeing 9 records is because the syntax you are using is the one for left outer joins in Linq.
What might work is using subqueries to get the data you want in a format you want it.
For example
var res = from cpr in db.CiscoPhoneReport
join app in db.ApplicationSummary on cpr.PhoneReportID equals app.PhoneReportID
where cpr.PhoneReportID == phoneReportID
select new PhoneReport
{
AppSummary = new AppSummary
{
// Mappings
},
CSQModel = (from model in db.CSQActivityReport
where model.PhoneReportId == phoneReportID
select new CSQModel
{
// Mappings
}).ToList()
}
You were right that you need the CSQModels to be some sort of collection, be it a List or even a basic ICollection of type CSQModel. You can write another sub query for the CallDistributionSummary as needed.
For every master record, you have 3 records each in 2 separate child tables. Any join you do will give you 9 records (even if you go straight to T-SQL) unless you add some more information.
One way to do this in SQL is to join record 1 from table A to record 1 from table B, you would need an indexer to do this. One option in T-SQL is to use the ROW_NUMBER() function on each of the child tables and use that value in the join. But, the ROW_NUMBER() hasn't been extended to LINQ.
If you can't stand getting getting duplicate records, and just doing a Distinct() call for each child result set. Then you could do this as two or 3 separate queries.
NOTE: You can bundle this into 3 result sets in a stored proc.. You can easily get EntityFramework to deserialize each result into your POCO's..
var objCtx = ((IObjectContextAdapter)ctx).ObjectContext;
using (SqlCommand cmd = ctx.Database.Connection.CreateCommand() as SqlCommand)
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "<your proc here>";
var param = cmd.CreateParameter();
param.ParameterName = "#param1";
param.Value = someValue;
cmd.Parameters.Add(param);
await cmd.Connection.OpenAsync();
using (var reader = await cmd.ExecuteReaderAsync())
{
var results = objCtx.Translate<type1Here>(reader).ToList();
reader.NextResult();
var results2 = objCtx.Translate<type2Here>(reader).ToList();
reader.NextResult();
var results3 = objCtx.Translate<type3Here>(reader).ToList();
reader.NextResult();
}
}
You can serialize your object:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(GenericObject.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, GenericObject);
string json = Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
return json;
I have 2 tables in the database :
Table: Order (item_id)
Table: Item ( item_id)
When I'm doing the inner join in entity framework, as you can see below, I need to return in one list the result to manipulate this. Usually when I do the select in one single table , I return a LIST from the entity with the tables name, but I dont know how can I return a LIST when I have 2 or more entity , I mean, using inner join, I would like to return a List that I can manipulate in other class. When I use for only one entity, it is perfect and easy.
public List<????????> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
});
return _result;
}
I don't know how to return it !! I tried to use the .TOLIST(), but still coming "anonymous".
Thank you
First you need to create a custom type like
public class OrderItems
{
public int Order_numer { get; set; }
public int Total { get; set; }
public string Item_code { get; set; }
public int Item_qty { get; set; }
}
After then modify your function like
public List<OrderItems> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new OrderItems()
{
Order_numer= a.order_numer,
Total= a.total,
Item_code=b.item_code,
Item_qty=b.item_qty
}).ToList();
return _result;
}
I hope it will work for you.
You can create a compound model that has a property representing each entity.
public class CompoundModel
{
public Entities.Order { get; set; }
public Entities.Item { get; set; }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
Order = a
Item = b
});
return _result;
}
Alternatively, if you want to flatten your structure, you can create a class that only has four properties.
public class CompoundModel
{
public string OrderNumber { get; set; }
public int Total { get; set; }
public string ItemCode { get; set; }
public int ItemQuantity { get; set }
}
public List<CompoundModel> getTransdataByStatus(string status)
{
contenxt = new Finance_ManagementEntity();
var _result = (from a in contenxt.Orders
join b in contenxt.Items on a.item_id equals b.item_id
select new CompoundModel
{
OrderNumber = a.order_number,
Total = a.total,
ItemCode = b.item_code,
ItemQuantity = b.item_qty
});
return _result;
}
The problem with your code is this part:
select new // This will create an anonymous type
{
a.order_numer,
a.total,
b.item_code,
b.item_qty
}
As the select generates an anonymous type you will get a list of theses anonymous types as a result of the query. In order to get a list typed results, you need to specify the type in the select-clause:
select new TypeYouWantToReturn() // This will create an real type
{
PropA = a.order_numer, // You also need to specify the properties
PropB = a.total, // of the class that you want to assign
PropC = b.item_code, // the resulting values of the query.
PropD = b.item_qty
}
Now the result of the query will return a list of real types. You need to finally call .ToList() so you get a list instead of the IEnumerable that the select statement will return.
I have two views in my model.
I basically need to do an INNER JOIN on them based on three columns:
dataSource
ShowID
EpisodeID
The first thing I don't know how to do is add the SQL "AND" operator to the LINQ expression.
The second thing is, I don't know how to SELECT the JOINED table.
Can someone give me a hand?
var query = (from s in db.TVData_VW_ShowList
from z in db.TVData_VW_Schedule
where s.dataSource = z.dataSource
&& s.ShowID = z.ShowID
&& s.EpisodeId = z.EpisodeId select ...
You can use anonymous types to your advantage here, both to join across multiple columns, and to project into a new type containing data from both sides of the join. Here's a working example using Linq to objects:
namespace LinqExample
{
class Program
{
static void Main()
{
var Shows = new List<ShowData> { new ShowData { dataSource = "foo", EpisodeID = "foo", ShowID = "foo", SomeShowProperty = "showFoo" }};
var Schedules = new List<ScheduleData> { new ScheduleData { dataSource = "foo", EpisodeID = "foo", ShowID = "foo", SomeScheduleProperty = "scheduleFoo" } };
var results =
from show in Shows
join schedule in Schedules
on new { show.dataSource, show.ShowID, show.EpisodeID }
equals new { schedule.dataSource, schedule.ShowID, schedule.EpisodeID }
select new { show.SomeShowProperty, schedule.SomeScheduleProperty };
foreach (var result in results)
{
Console.WriteLine(result.SomeShowProperty + result.SomeScheduleProperty); //prints "showFoo scheduleFoo"
}
Console.ReadKey();
}
}
public class ShowData
{
public string dataSource { get; set; }
public string ShowID { get; set; }
public string EpisodeID { get; set; }
public string SomeShowProperty { get; set; }
}
public class ScheduleData
{
public string dataSource { get; set; }
public string ShowID { get; set; }
public string EpisodeID { get; set; }
public string SomeScheduleProperty { get; set; }
}
}
So to join you can use the join keyword then use on to specify the conditions. && (the logical and operator in C#) will be translated to the SQL AND keyword.
Also, in EF they have what are known as "implicit joins" meaning if I have TableA with a foreign key to TableB, call it fKey.
Doing where TableA.fKey == TableB.pKey will cause the provider to put a join there. To select you simply need to do;
select new { prop1 = TableA.Prop1, prop2 = TableB.Prop1 }
this will create a new anonymous which selects values from both tables.
Below is a more complete example of the join syntax. I think it uses all of the things you asked about;
var result = from a in TableA
join b in TableB on a.fKey equals b.pKey && b.Status equals 1
select new { a.Prop1, a.Prop2, b.Prop1 };
First you need to create an auxiliar class that contains the columns of both views, something like:
public class viewItem
{
public int ShowID { get; set; }
public int EpisodeID { get; set; }
public int dataSource { get; set; }
...
}
then your linq query would be:
var query = (from s in db.TVData_VW_ShowList
join z in db.TVData_VW_Schedule
on s.dataSource equals z.dataSource
where s.ShowID == z.ShowID
&& s.EpisodeID == z.EpisodeID
select new viewItem {
ShowID = s.ShowID,
EpisodeID = s.EpisodeID,
dataSource = s.dataSource,
...
}