I have the following class
public class Booking
{
public string Group { get; set; }
public BookingType Type { get; set; }
public BookingStatus Status { get; set; }
public InvoiceFreq { get; set; }
public InvoiceLevel { get; set; }
}
That I'd need to group them by all properties in Linq so that the last two properties form one new field in the grouped result.
Like this:
Group Type Status InvoiceType
-------------------------------------------
Group1 Online New Daily-Single
Group2 Phone Accepted Daily-Single
Group3 Store Accepted Weekly-Single
Group3 Store Accepted Weekly-Bulk
Here the InvoiceFreq will be Daily / Weekly and the InvoiceLevel = Single or Bulk.
The query I have so far is this:
var query = from b in Bookings
group b by new
{
b.Group,
b.Type,
b.Status,
b.InvoicingFrequency,
b.InvoicingLevel
} into bookingGroup
select new BookingSummaryLine()
{
Group = bookingGroup.Key.UserGroup,
Type = bookingGroup.Key.UserGroup,
Status = bookingGroup.Key.FinancialStatus,
InvType = String.Format({0}-{1},bookingGroup.Key.InvoicingFrequency, bookingGroup.Key.InvoicingLevel
};
This of course does not give the desired result as the two properties are in the anonymous type separately.
Is there any way to achieve this in Linq?
This should work:
var query = from b in Bookings
group b by new
{
b.Group,
b.Type,
b.Status,
InvType = String.Format({0}-{1},b.InvoicingFrequency, b.InvoicingLevel)
} into bookingGroup
select new BookingSummaryLine()
{
Group = bookingGroup.Key.UserGroup,
Type = bookingGroup.Key.UserGroup,
Status = bookingGroup.Key.FinancialStatus,
InvType = bookingGroup.Key.InvType
};
I'm not as sure about the syntax for linq but for lambda I would use this. Basically use distinct if your trying to group on all columns like that.
Context.Booking.Distinct().Select(z=> new BookingSummaryLine { Group = z.Group, Type = z.Type, Status = z.Status, InvType = (z.InvoiceFrequency + "-" + z.InvoiceLevel });
Related
I am currently loading two Orders and Colors tables, I wanted the Colors table to list the items that have the ID equal to Orders. For this, what occurred to me was to assign the IdOrders values to a variable and compare it with my IdOrders (in my table Colors), but it is not possible to assign the database's balance to my variable
My tables:
public partial class Orders
{
public int ID_Orders { get; set; }
public Nullable<System.DateTime> Data_Registo { get; set; }
public string Num_Encomenda { get; set; }
public string Ref_Cliente { get; set; }
}
public partial class Colors
{
public int ID_Orders { get; set; }
public int ID_Programa_Malha { get; set; }
public int ID_Linha_Cor { get; set; }
public string Cor { get; set; }
}
I am working with a database already in operation and possible these tables are already used in a sql join but not how to process that information.
As I said the first thing I remembered was to do this:
My Controller:
var id = from d in db.Orders
select d.ID_Orders;
var color = db.Colors.Where(x => x.ID_Orders = id).ToList();
var tables = new EncomendaViewModel
{
Orders= db.Orders.ToList(),
Colors= color.ToList(),
};
return View(tables);
Error in id: CS0029 C# Cannot implicitly convert type to 'int'
Is it possible to process the data in this way?
Thanks for anyone who can help!
-------------------(Update)------------------------------------------------
Using == cs0019 operator '==' cannot be applied to operands of type
My view in Broswer
dbEntities sd = new dbEntities();
List<Orders> orders= sd.Orders.ToList();
List<Colors> colers= sd.Colors.ToList();
var multipletable = from c in orders
join st in colers on c.ID_Programa equals st.ID_Programa into table1
from st in table1.DefaultIfEmpty()
select new MultipleClass { orders= c, colers= st };
There could be one or more values returned from the below query.
var id = from d in db.Orders
select d.ID_Orders;
That is the reason why it was throwing an error.
So lets try it this way
var color = db.Colors.Where(x => id.Contains(x.ID_Orders)).ToList();
public class OrderWithColorsViewModel
{
public Order order { get; set; }
public List<Colors> colers{ get; set; }
}
Public class TestOrderController : Controller
{
public DailyMVCDemoContext db = new DailyMVCDemoContext();
public ActionResult Index()
{
var orders= db.Orders.ToList();
var colers = db.Colors.ToList();
var result = (from c in orders
join st in colers on c.ID_Orders equals st.id into table1
select new OrderWithColorsViewModel { order =c, colers =
table1.ToList() }).ToList();
return View(result);
}
}
credits: YihuiSun
I have two lists of Client Object:
public class Client
{
public int ClientID { get; set; }
public string Name { get; set; }
public string DCCode { get; set; }
public string CountryName { get; set; }
}
my list A hold 4 items ClientID , and name fields are populated,
My List B Hold the same 4 items but there is no name and hold the ClientID DCCode, and CountryName
i need to either Update list A DCCode and Countryname with corresponding values in list B
or create List C which it hold 4 items with complete value of list A and B together
Like :
List C L: item 1 : ClientID : 1, Name: XXYY, DCCode :4, CountryName: UK
I can do this using for loop, but i have been trying to use LINQ
i have tried the following codes but i could not find the correct way to get the result i want
Solution 1
Clients1.Where(i => Clients2.Any(a=> i.CLinetID == a.CLinetID))
Solution 2:
Clients1.Concat(Clients1).Concat(Clients2).ToList();
Any help would be welcomed
As you have the ClientID field populated in both lists join them by that property and project a new object populated with all fields:
var result = from c1 in Clients1
join c2 in Clients2 on c1.ClientID equals c2.ClientID
select new Client { ClientID = c1.ClientID, Name = c1.Name, DCCode = c2.DCCode, CountryName = c2.CountryName };
This will create the third list. You can also update the items of Clients1 likewise:
foreach (var c1 in Clients1)
{
var c2 = Clients2.FirstOrDefault(i => i.ClientID == c1.ClientID);
if(c2 != null)
{
c1.DCCode = c2.DCCode;
c1.CountryName = c2.CountryName;
}
}
For updating entities in first list you can create dictionary from second list - that will allow you to quickly find corresponding entity with O(1):
var clientsByID = listB.ToDictionary(c => c.ClientID);
foreach(var clientA in listA)
{
var clientB = clientsByID[clientA.ClientID];
clientA.DCCode = clientB.DCCode;
clientA.CountryName = clientB.CountryName;
}
You can also join two lists on ClientID property and produce new list from results (if enumerable is good for you, then I would go with query syntax instead):
var listC = listA.Join(listB,
a => a.ClientID,
b => b.ClientID,
(a,b) => new Client {
ClientID = a.ClientID,
Name = a.Name,
DCCode = b.DCCode,
CountryName = b.CountryName
}).ToList();
I am using visjs.net to display a schedule
I'm having trouble writing LINQ to populate a list that contains a property that is an array
Here is the visjs documentation visjs doco
and some example code visjs source code
Here is an abridged version of the sample in javascript. I need to populate this JSON from a MVC controller instead of javascript
var groups = new vis.DataSet();
groups.add([
{
id: 1,
content: "Lee",
nestedGroups: [11,12]
}
]);
groups.add([
{
id: 11,
content: "cook",
},
{
id: 12,
content: "shop",
}
]);
spoiler alert: I don't know how to populate the nestedGroups property
This is the class I built for it:
public class TimelineGroups
{
public int id { get; set; }
public string content { get; set; }
public string className { get; set; }
public string orderBy { get; set; }
public string[] nestedGroups { get; set; }
}
This is the controller method that populates it, excluding the nestedGroups property, and this works just fine:
public JsonResult EmployeeGroups()
{
List<TimelineGroups> e = (
from emp in db.Employees
where emp.Emp_Status == 1 && emp.EmployeeRole.IsChargeable == "Y"
orderby emp.EmpRole_ID, emp.Emp_Last_Name
select new TimelineGroups()
{
id = emp.Emp_ID,
content = emp.Emp_Name,
orderBy = emp.EmpRole_ID.ToString(),
className = "bte-" + emp.EmployeeRole.EmpRoleName
}
).ToList();
return Json(e, JsonRequestBehavior.AllowGet);
}
This all works correctly but now I want to add nested groups.
But I don't know the LINQ required to 'pivot' the required data into an array inside a collection.
This is what I have so far:
public JsonResult EmployeeClientGroups()
{
// First load the client list which are children of employees
List<TimelineGroups> cg = (
from sw in db.ScheduleWorks
where sw.EndDate > DateTime.Now
select new TimelineGroups()
{
id = sw.Employee.Emp_ID * 1000 + sw.CustomerId,
content = sw.Customer.Customer_Name
}).Take(1000).Distinct().ToList();
// now load the employee list
// This includes client children
List<TimelineGroups> eg = (
from sw in db.ScheduleWorks
where sw.EndDate > DateTime.Now
select new TimelineGroups()
{
id = sw.Employee.Emp_ID,
// How do I populate this with sw.Employee.Emp_ID * 1000 + sw.CustomerId
nestedGroups = // What magic do I put here?
content = sw.Employee.Emp_Name,
}).Take(1000).Distinct().ToList();
// Add the employee groups to the client groups
cg.AddRange(eg);
return Json(cg, JsonRequestBehavior.AllowGet);
}
I need to get all the client ID's for a given Employee and "pivot" them into an array, suitable to post back as JSON
To make them unique and match the children id's, the value I need to pivot in is:
sw.Employee.Emp_ID * 1000 + sw.CustomerId
Can this be done inline in a LINQ statement?
So it turns out this was kind of answered here but I will document my solution
This is the code that I eventually used:
public class TimelineGroups
{
public string id { get; set; }
public string content { get; set; }
public string className { get; set; }
public string orderBy { get; set; }
public List<string> nestedGroups { get; set; }
}
List<TimelineGroups> eg = (
from sw in db.ScheduleWorks
where sw.EndDate > DateTime.Now
where sw.Employee.Emp_Status == 1
group (sw.EmployeeId.ToString() + "." + sw.CustomerId.ToString())
by new {
id = sw.EmployeeId.ToString(),
EmpName = sw.Employee.Emp_Name,
EmpOrder = sw.Employee.EmpRole_ID.ToString()
}
into g
select new TimelineGroups()
{
id = g.Key.id,
// find the list of employee+client keys
nestedGroups = g.ToList(),
content = g.Key.EmpName,
orderBy = g.Key.EmpOrder
})
.Take(1000)
.ToList();
Note no Distinct
The argument to group is the field holding the values that i want to "pivot"
then the part after by is the actual 'key' that will be grouped on
I needed to use a List() rather than an array (maybe I could've used ToArray though?)
Once this is grouped into an intermediate variable g, you can use g.ToList() to get the 'pivoted' values
Hopefully this will help someone else one day, maybe even someone using the visjs library
#Tetsuya Yamamoto fiddle pointed me in the right direction
I am using Linq to SQL in a WebApi to return a list of objects from a database to a frontend.
Let's say the model looks something like this:
public class Course
{
public int ID { get; set; }
public string NAME { get; set; }
}
public class Schedules
{
public int id { get; set; }
public int courseid
public datetime start { get; set; }
}
In addition my Linq-to-SQL inside of one Controller looks something like this:
...
...
var list = (from xx in xx.Courses
select new Course
{
ID = xx.ID,
NAME = xx.NAME,
Schedules = (from yy in yy.Schedules
where xx.ID == yy.courseid
select new Schedules
{
id = yy.id,
courseid = yy.courseid,
start = yy.start
}).toList()
}).toList()
...
...
Now I need to order "list" by the minValue of Schedules.start in an ascending order. That means, that the output should give me the element with the earliest start first. In addition Courses with no planned schedule should be given out at the end.
In the end the output should look like this:
[{"ID":5, "NAME":"NAME1", "Schedules":[{"id":10, "courseid":5, "start":"2017-12-15 00:00:00.000"}, {"id":8, "courseid":5, "start":"2017-12-20 00:00:00.000"}]}],[{"ID":1, "NAME":"NAME1", "Schedules":[{"id":9, "courseid":1, "start":"2017-12-16 00:00:00.000"}, {"id":2, "courseid":1, "start":"2017-12-17 00:00:00.000"}]}]
Thanks in advance.
I was in such a situation where I need to sort the parent depend on the child property's value.
var list = (from xx in xx.Courses
select new Course
{
ID = xx.ID,
NAME = xx.NAME,
Schedules = (from yy in yy.Schedules
where xx.ID == yy.courseid
select new Schedules
{
id = yy.id,
courseid = yy.courseid,
start = yy.start
}).toList()
}).OrderBy(mc => mc.Schedules.Min(dc => dc.start)).toList()
I have a class that acts as a summary which is going to be passed to an MVC View as an IEnumerable. The class looks like:
public class FixedLineSummary
{
public long? CustomerId { get; set; }
public string CustomerName { get; set; }
public int? NumberOfLines { get; set; }
public string SiteName { get; set; }
}
The results returned from the db have all of the single entries and so I use linq to summarise these using:
var summary = (from r in result
let k = new {r.CustomerId, CustomerName = r.CompanyName, r.SiteName}
group r by k into t
select new
{
t.Key.CustomerId,
t.Key.CustomerName,
t.Key.SiteName,
Lines = t.Sum(r => r.lines)
});
When I try and cast the results into my object however I just keep getting an error that:
Instance argument: cannot convert from 'System.Linq.IQueryable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<Domain.Entities.FixedLineSummary>'
Is there a way to cast the results of the linq query into an enumerable of my class?
You should change the projection to create your class, rather than an anonymous type:
var summary = from r in result
let k = new {r.CustomerId, CustomerName = r.CompanyName, r.SiteName}
group r by k into t
select new FixedLineSummary
{
CustomerId = t.Key.CustomerId,
CustomerName = t.Key.CustomerName,
SiteName = t.Key.SiteName,
NumberOfLines = t.Sum(r => r.lines)
};
You cannot cast the anonymous type to FixedLineSummary since both are not related at all(for the compiler). Instead you need to create instances of your class manually:
IEnumerable<FixedLineSummary> summaries = summary
.Select(s => new FixedLineSummary
{
CustomerId = s.CustomerId,
CustomerName = s.CustomerName,
NumberOfLines = s.NumberOfLines,
SiteName = s.SiteName
})
.ToList();