I have the following code:
public IEnumerable<Content.Grid> DetailsBase(string pk)
{
var data = contentRepository.GetPk(pk);
var refType = this.GetRefType(pk);
var refStat = this.GetRefStat(pk);
var type = referenceRepository.GetPk(refType);
var stat = referenceRepository.GetPk(refStat);
var dataOut =
from d in data
join s in stat on d.Status equals s.RowKey into statuses
from s in statuses.DefaultIfEmpty()
join t in type on d.Type equals t.RowKey into types
from t in types.DefaultIfEmpty()
select new Content.Grid
{
PartitionKey = d.PartitionKey,
RowKey = d.RowKey,
Order = d.Order,
Title = d.Title,
Status = s == null ? "" : s.Value,
StatusKey = d.Status,
Type = t == null ? "" : t.Value,
TypeKey = d.Type
};
return dataOut;
}
and this class:
public class Grid
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
// Counter
public int Row { get; set; }
//
public int Order { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string StatusKey { get; set; }
public string Type { get; set; }
}
Is there a way that I can set the value of Row to increment. In another select I used this:
return dataIn
.OrderBy(item => item.Order)
.Select((t, index) => new Content.Grid()
{
PartitionKey = t.PartitionKey,
RowKey = t.RowKey,
Row = index + 1,
Is there a way I could use something similar for my first select?
Update:
I have the following which seems to work but not sure how I can join these two selects:
public IList<Content.Grid> GetContentGrid(string pk)
{
var data =
from d in contentRepository.GetPk(pk)
join s in referenceRepository.GetPk(this.GetRefStat(pk))
on d.Status equals s.RowKey into statuses
from s in statuses.DefaultIfEmpty()
join t in referenceRepository.GetPk(this.GetRefType(pk))
on d.Type equals t.RowKey into types
from t in types.DefaultIfEmpty()
select new Content.Grid
{
PartitionKey = d.PartitionKey,
RowKey = d.RowKey,
Order = d.Order,
Title = d.Title,
Status = s == null ? "" : s.Value,
StatusKey = d.Status,
Type = t == null ? "" : t.Value,
TypeKey = d.Type,
Link = d.Link,
Notes = d.Notes,
TextLength = d.TextLength,
// AuditableTable
Created = d.Created ?? new DateTime(2012, 1, 1),
CreatedBy = d.CreatedBy ?? "n/a",
Modified = d.Modified ?? new DateTime(2012, 1, 1),
ModifiedBy = d.ModifiedBy ?? "n/a"
};
return data
.OrderBy(item => item.Order)
.Select((t, index) => new Content.Grid()
{
PartitionKey = t.PartitionKey,
RowKey = t.RowKey,
Row = index + 1,
Order = t.Order,
Title = t.Title,
Status = t.Status,
StatusKey = t.StatusKey,
Type = t.Type,
TypeKey = t.TypeKey,
Link = t.Link,
Notes = t.Notes,
TextLength = t.TextLength,
})
.ToList();
}
You can't specify an index-related projection in a query expression, but you could do something like:
var dataOut = from d in data
join s in stat on d.Status equals s.RowKey into statuses
from s in statuses.DefaultIfEmpty()
join t in type on d.Type equals t.RowKey into types
from t in types.DefaultIfEmpty()
select new { d, s, t };
return dataOut.Select((x, index) => new Content.Grid {
PartitionKey = x.d.PartitionKey,
RowKey = x.d.RowKey,
Order = x.d.Order,
Title = x.d.Title,
Status = x.s == null ? "" : x.s.Value,
StatusKey = x.d.Status,
Type = x.t == null ? "" : x.t.Value,
TypeKey = x.d.Type,
Row = index
};
Note that without specifying any ordering, however, this may fail - or just give unreliable ordering.
Related
I have three tables: Courses, CourseLocations, CourseSchedules
Each Course can be held in one or more Locations (1-to-many)
Each Location can host one or more Schedules (1-to-many)
I need to get all the courses, unique names, that have a Schedules.Date> Today and show also the MAX value of the date contained in the table CourseSchedules
My current linq code is:
var courses = (from c in db.Courses
join cl in db.CourseLocations on c.CourseID equals cl.CourseID
join cs in db.CourseSchedules on cl.CourseLocationID equals cs.CourseLocationID
where c.CourseStatusID == 1 && c.DeleteDate == null && ((c.CourseCategoryID == 1 && cs.EndDate >= courseEndDateFilter) || (c.CourseCategoryID == 3))
select new
{
c.CourseID,
CourseName = c.Name,
CourseEndDate = cs.EndDate
}).Distinct().OrderBy(o => o.CourseCategoryID).ThenBy(o => o.CourseName);
Where courseEndDateFilter is a variable used to define the date to filter.
The problem with the above query is that I get all the courses duplicated and not only the one with the MAX value of cs.EndDate
Is there a way (efficient) to do it?
#Ehsan is correct. You need a group by and then get the max value of EndDate. Given the following models:
public class Course
{
public int CourseID { get; set; }
public string Name { get; set; }
public int CourseStatusID { get; set; }
public int CourseCategoryID { get; set; }
public DateTime? DeleteDate { get; set; }
}
public class CourseLocation
{
public int CourseLocationID { get; set; }
public int CourseID { get; set; }
}
public class CourseSchedules
{
public int CourseLocationID { get; set; }
public DateTime EndDate { get; set; }
}
I created the following in memory objects:
var courses = new List<Course>
{
new Course { CourseID = 1, Name = "Test1", CourseCategoryID = 1, CourseStatusID = 1, DeleteDate = null },
new Course { CourseID = 2, Name = "Test2", CourseCategoryID = 1, CourseStatusID = 1, DeleteDate = null },
new Course { CourseID = 3, Name = "Test3", CourseCategoryID = 3, CourseStatusID = 1, DeleteDate = null }
};
var courseLocations = new List<CourseLocation>
{
new CourseLocation{ CourseID = 1, CourseLocationID = 1 },
new CourseLocation{ CourseID = 2, CourseLocationID = 1 },
new CourseLocation{ CourseID = 3, CourseLocationID = 1 },
new CourseLocation{ CourseID = 1, CourseLocationID = 2 },
new CourseLocation{ CourseID = 2, CourseLocationID = 2 },
new CourseLocation{ CourseID = 3, CourseLocationID = 2 }
};
var courseSchedules = new List<CourseSchedules>
{
new CourseSchedules { CourseLocationID = 1, EndDate = DateTime.Now.AddDays(10) },
new CourseSchedules { CourseLocationID = 1, EndDate = DateTime.Now.AddYears(1) }
};
Then the query would be the following to get Max EndDate:
var result = (from c in courses
join cl in courseLocations on c.CourseID equals cl.CourseID
join cs in courseSchedules on cl.CourseLocationID equals cs.CourseLocationID
where c.CourseStatusID == 1 && c.DeleteDate == null &&
(c.CourseCategoryID == 1 && cs.EndDate >= DateTime.Now || c.CourseCategoryID == 3)
select new
{
c.CourseID,
CourseName = c.Name,
CourseEndDate = cs.EndDate,
c.CourseCategoryID
})
.GroupBy(arg => new
{
arg.CourseID,
arg.CourseName,
arg.CourseCategoryID
})
.Select(grouping => new
{
grouping.Key.CourseID,
grouping.Key.CourseName,
CourseEndDate = grouping.Max(arg => arg.CourseEndDate),
grouping.Key.CourseCategoryID
})
.OrderBy(o => o.CourseCategoryID)
.ThenBy(o => o.CourseName);
I'm not sure this will work since it's not like I can actually compile it.
The problem I see right away is that you're filter by a few things at the base, some of which don't include the locations but you want the date from the locations anyway...
var courses = (from c in db.Courses
join cl in db.CourseLocations on c.CourseID equals cl.CourseID
join cs in db.CourseSchedules on cl.CourseLocationID equals cs.CourseLocationID
where c.CourseStatusID == 1 && c.DeleteDate == null && (c.CourseCategoryID == 3 ||
db.CourseLocations.Any(cl => cl.CourseID equals c.CourseID &&
db.CourseSchedules.Any(cs => cs.CourseLocationID equals cl.CourseLocationID &&
((c.CourseCategoryID == 1 && cs.EndDate >= courseEndDateFilter))
)
))
select new
{
c.CourseID,
CourseName = c.Name,
CourseEndDate = db.CourseSchedules.Where(cs => db.CourseLocations.Any(cl => cl.CourseID equals c.CourseID && cs.CourseLocationID equals cl.CourseLocationID)).Max(cs => cs.EndDate),
c.CourseCategoryID
});
I have two table first one is ReservationVehicleDetail = RVD, and the second one is Employee = EMP
In RVD has two column PrimaryDriverId and SecondaryDriverId both have mapped to EmployeeId of EMP table
My question is how to get data of Employee table using those two Ids.
Here is my code:
vm.BookVehicleDetailList = db.ReservationVehicleDetails.Where(x => x.ReservationId == vm.ReservationId && x.Status == Constant.ACTIVE).Select(v => new BookVehicleDetailModel()
{
VehicleImageURL = v.Vehicle.PictureURL,
IsDutySlipClosed = v.IsDutySlipClosed.HasValue ? v.IsDutySlipClosed.Value : false,
ReservationVehicleDetailId = v.ReservationVehicleDetailIId,
VehicleId = v.VehicleId.HasValue ? v.VehicleId.Value : 0,
VehicleCategory = v.VehicleCategory,
IsAC = v.IsAC,
ACorNonAC = v.IsAC ? "AC" : "Non AC",
FuelType = v.FuelType,
SeatingCapacity = v.Capacity,
RegistrationNumber = v.RegistrationNumber,
PrimaryDriverId = v.PrimaryDriverId.HasValue ? v.PrimaryDriverId.Value : 0,
PrimaryDriverName = v.PrimaryDriverId.HasValue ? v.Employee.FirstName : v.PrimaryDriverName,
SecondaryDriverId = v.SecondaryDriverId.HasValue ? v.SecondaryDriverId.Value : 0,
SecondaryDriverName = v.SecondaryDriverId.HasValue ? v.Employee.FirstName : v.SecondaryDriverName,
TariffType = v.TariffType,
DailyMinimumDistance = v.DailyMinimumDistance.HasValue ? v.DailyMinimumDistance.Value : 0,
TariffPerUnitDistance = v.TariffPerUnitDistance.HasValue ? v.TariffPerUnitDistance.Value : 0,
ExternalCompanyName = v.ExternalCompanyName,
StartDistanceReading = v.StartDistanceReading.HasValue ? v.StartDistanceReading.Value : 0,
EndDistanceReading = v.EndDistanceReading.HasValue ? v.EndDistanceReading.Value : 0,
GarageDistanceReading = v.GarageDistanceReading.HasValue ? v.GarageDistanceReading.Value : 0,
GrossTariff = v.GrossTariff.HasValue ? v.GrossTariff.Value : 0,
Distance = (v.StartDistanceReading.HasValue ? v.StartDistanceReading.Value : 0) + " - " + (v.EndDistanceReading.HasValue ? v.EndDistanceReading.Value : 0) + " - " + (v.GarageDistanceReading.HasValue ? v.GarageDistanceReading.Value : 0) + " (" + ((v.EndDistanceReading.HasValue ? v.EndDistanceReading.Value : 0) - (v.StartDistanceReading.HasValue ? v.StartDistanceReading.Value : 0) + (v.GarageDistanceReading.HasValue ? v.GarageDistanceReading.Value : 0)) + " KM)",
}).ToList();
Right now data return based on the first PrimaryDriverId means PrimaryDriverId and SecodaryDriverId both are different but PrimaryDriverName and SecondaryDriverName both are same after executing the query.
So how to solve this issue.
Your v.employee is only related to one Employee. So you get the same Employee object.
I am presuming you have a model that looks something like this:
public class RVD
{
public int Id { get; set; }
public Employee Employee { get; set; } //This will only link to one Employee
public int PrimaryDriverId { get; set; }
public int SecondaryDriverId { get; set; }
}
You can either look at changing the Linq to add a join so that you can map RVD to two different employees:
e.g.
var result = (from r in rvds
join e1 in emps on r.PrimaryDriverId equals e1.Id
join e2 in emps on r.SecondaryDriverId equals e2.Id
where r.Id == 1
select new
{
PrimaryDriverName = e1.Name,
SecondaryDriverName = e2.Name
}).ToList();
Or you can update your model.
e.g.
public class RVD
{
public int Id { get; set; }
public Emp PrimaryDriver { get; set; }
public Emp SecondaryDriver { get; set; }
}
public class Emp
{
public int Id { get; set; }
public string Name { get; set; }
}
Then you can do this:
var emp1 = new Emp() { Id = 1, Name = "John" };
var emp2 = new Emp() { Id = 2, Name = "Dave" };
var rvd = new RVD() { Id = 1, PrimaryDriver = emp1, SecondaryDriver = emp2 };
List<RVD> rvds = new List<RVD>();
rvds.Add(rvd);
var result = rvds.Where(x => x.Id == 1).Select(x => new
{
PrimaryDriverName = x.PrimaryDriver.Name,
SecondaryDriverName = x.SecondaryDriver.Name,
}).ToList();
I guess You might have put this conditions wrong.
PrimaryDriverName = v.PrimaryDriverId.HasValue ? v.Employee.FirstName : v.PrimaryDriverName,
SecondaryDriverName = v.SecondaryDriverId.HasValue ? v.Employee.FirstName : v.SecondaryDriverName
I guess you want to assign the Driver Name if the Id is present else you want to assign the Employee.FirstName but it seems like you are assigning the Employee.FirstName when you have Id's present for both primary as well as the secondary driver.
I guess you should try switching the condition as below.
PrimaryDriverName = v.PrimaryDriverId.HasValue ? v.PrimaryDriverName : v.Employee.FirstName,
SecondaryDriverName = v.SecondaryDriverId.HasValue ? v.SecondaryDriverName : v.Employee.FirstName,
I am trying to convert a flat list to nested list.
This is my flat list:
public class DefectLocationCount {
public string LocationName { get; set; }
public string DefectName { get; set; }
public int TotalCount { get; set; }
}
This is my nested list:
public class DefectLocationOutput
{
public string DefectName{ get; set; }
public List<int> TotalCount{ get; set; }
}
This is my linq query to populate the flat list
var results = (from def in rep.tblDefects
join defLoc in
(from defDet in rep.tblMovementDefects
join det in rep.tblMovementDetails on defDet.MovementDetailId equals det.MovementDetailId
join loc in rep.tblLocations on det.ToLocationId equals loc.LocationId
join hed in rep.tblMovementHeaders on det.MovementHeaderId equals hed.MovemenHeaderId
where hed.DateCreated >= fromDate && hed.DateCreated <= toDate
select new { loc.LocationName, defDet.DefectId, loc.LocationId }
) on def.DefectId equals defLoc.DefectId
group def by new { def.DefectName, defLoc.LocationId, defLoc.LocationName } into joined
select new
{
LocationName = joined.Key.LocationName,
LocationId = joined.Key.LocationId,
DefectName = joined.Key.DefectName,
TotalCount = joined.Count()
}).OrderBy(x => x.LocationId);
Edit
This is what i am trying to achieve
In the format of List<DefectLocationOutput> and instead of null values have 0.
How can this be done?
I didn't really understand what result are you awaiting, but maybe this will help you:
DefectLocationCount cl1 = new DefectLocationCount()
{
DefectName = "Name1",
LocationName = "Location1",
TotalCount = 2
};
DefectLocationCount cl2 = new DefectLocationCount()
{
DefectName = "Name1",
LocationName = "Location2",
TotalCount = 3
};
DefectLocationCount cl3 = new DefectLocationCount()
{
DefectName = "Name2",
LocationName = "Location3",
TotalCount = 6
};
var lstCl = new List<DefectLocationCount>();
lstCl.Add(cl1);
lstCl.Add(cl2);
lstCl.Add(cl3);
var result = lstCl.GroupBy(x => x.DefectName).Select(x => new DefectLocationOutput() { DefectName = x.Key, TotalCount = lstCl.Where(y => y.DefectName == x.Key).Select(y => y.TotalCount).ToList() });
Is there a way to progressively / conditionally add joins to a query? I am creating a custom reporting tool for a client, and the client is given a list of objects he/she can select to query on. There will always be a base object used in the query ("FWOBid").
So, for example, if the customer selects objects "FWOBid", "FWOItem", and "FWOSellingOption", I'd want to do this:
var query = from fb in fwoBids
// if "FWOSellingOption", add this join
join so in sellingOptions on fb.Id equals so.BidId
// if "FWOItem", add this join
join i in fwoItems on fb.Id equals i.FWOBidSection.BidId
// select "FWOBid", "FWOItem", and "FWOSellingOption" (everything user has selected)
select new { FWOBid = fb, FWOSellingOption = so, FWOItem = i };
The trick is the customer can select about 6 objects that are all related to each other, resulting in many different combinations of joins. I'd like to avoid hard coding those if possible.
One option is to do some custom join combined with left joins.
A decent TSQL backend should not get any drawbacks in terms of performance for always using all the joins, since the optimers would just remove the join if the condition is always false. But this should be checked out.
bool joinA = true;
bool joinB = false;
bool joinC = true;
var query = from fb in fwoBids
join so in sellingOptions on new { fb.Id, Select = true } equals new { Id = so.BidId, Select = joinA } into js
from so in js.DefaultIfEmpty()
join i in fwoItems on new { fb.Id, Select = true } equals new { Id = i.FWOBidSection.BidId, Select = joinB } into ji
from i in ji.DefaultIfEmpty()
join c in itemsC on new { fb.Id, Select = true } equals new { Id = c.BidId, Select = joinC }
select new
{
FWOBid = fb,
FWOSellingOption = so,
FWOItem = i,
ItemC = c
};
In the Linq query syntax this is not possible, or looking at the other answers hardly readable. Not much more readable but another possibility would be to use the extension methods (sort of pseudo code):
bool condition1;
bool condition2;
List<Bid> bids = new List<Bid>();
List<SellingOption> sellingOptions = new List<SellingOption>();
List<Item> items = new List<Item>();
var result = bids.Select(x => new {bid = x, sellingOption = (SellingOption)null, item = (Item)null});
if (condition1)
result = result.Join(
sellingOptions,
x => x.bid.Id,
x => x.BidId,
(x, sellingOption) => new { x.bid, sellingOption, item = (Item)null });
if (condition2)
result = result.Join(
items,
x => x.bid.Id,
x => x.BidId,
(x, item) => new { x.bid, x.sellingOption, item });
Just see this as a sort of a concept. It is essentially the same that Peter Duniho did.
The thing is, if you don't want to immediately join on all options if not necessary, then it won't look that nice. Perhaps you should try to join all now and don't worry about performance. Have you ever measured how slow or fast it might be? Think of it as "I don't need it now!". If performance is indeed a problem, then you can act on it. But if it is not, and you won't know if you never tried, then leave it as the six joins you mentioned.
It's hard to provide a really good example solution without a really good example problem. However, what I mean by "chain the queries" is something like this:
var query = from x in dba select new { A = x, B = (B)null, C = (C)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.A.Id equals y.Id
select new { A = x.A, B = y, C = x.C };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.A.Id equals y.Id
select new { A = x.A, B = x.B, C = y };
}
That is, based on the appropriate condition, query the previous result with another join. Note that to do this successfully, each query must produce the same type. Otherwise, it's not possible to assign a new query to the previous query result variable.
Note that while in the above, I simply have a separate property for each possible input type, I could have instead had the type simply have properties for the input columns, Id, Name, and then the Text properties from the B and C types (which would have to be named differently in the query result type, e.g. TextB and TextC). That would look like this:
var query = from x in dba select new { Id = x.Id, Name = x.Name,
TextB = (string)null, TextC = (string)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.Id equals y.Id
select new { Id = x.Id, Name = x.Name, TextB = y.Text, TextC = x.TextC };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.Id equals y.Id
select new { Id = x.Id, Name = x.Name, TextB = x.TextB, TextC = y.Text };
}
Here is a complete code example that includes the above logic in a runnable program:
class A
{
public string Name { get; private set; }
public int Id { get; private set; }
public A(string name, int id)
{
Name = name;
Id = id;
}
public override string ToString()
{
return "{" + Name + ", " + Id + "}";
}
}
class B
{
public int Id { get; private set; }
public string Text { get; private set; }
public B(int id, string text)
{
Id = id;
Text = text;
}
public override string ToString()
{
return "{" + Id + ", " + Text + "}";
}
}
class C
{
public int Id { get; private set; }
public string Text { get; private set; }
public C(int id, string text)
{
Id = id;
Text = text;
}
public override string ToString()
{
return "{" + Id + ", " + Text + "}";
}
}
[Flags]
enum JoinType
{
None = 0,
B = 1,
C = 2,
BC = 3
}
class Program
{
static void Main(string[] args)
{
A[] dba =
{
new A("A1", 1),
new A("A2", 2),
new A("A3", 3)
};
B[] dbb =
{
new B(1, "B1"),
new B(2, "B2"),
new B(3, "B3")
};
C[] dbc =
{
new C(1, "C1"),
new C(2, "C2"),
new C(3, "C3")
};
JoinType joinType;
while ((joinType = _PromptJoinType()) != JoinType.None)
{
var query = from x in dba select new { A = x, B = (B)null, C = (C)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.A.Id equals y.Id
select new { A = x.A, B = y, C = x.C };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.A.Id equals y.Id
select new { A = x.A, B = x.B, C = y };
}
foreach (var item in query)
{
Console.WriteLine(item);
}
Console.WriteLine();
}
}
private static JoinType _PromptJoinType()
{
JoinType? joinType = null;
do
{
Console.Write("Join type ['A' for all, 'B', 'C', or 'N' for none]");
ConsoleKeyInfo key = Console.ReadKey();
Console.WriteLine();
switch (key.Key)
{
case ConsoleKey.A:
joinType = JoinType.BC;
break;
case ConsoleKey.B:
joinType = JoinType.B;
break;
case ConsoleKey.C:
joinType = JoinType.C;
break;
case ConsoleKey.N:
joinType = JoinType.None;
break;
default:
break;
}
} while (joinType == null);
return joinType.Value;
}
}
I hope this is an improvement over previous answers.
public class Bids
{
public int Id { get; set; }
public double Price { get; set; }
}
public class BidSection
{
public int BidId { get; set; }
}
public class SellingOptions
{
public int BidId { get; set; }
public int Quantity { get; set; }
}
public class Item
{
public int ItemId { get; set; }
public BidSection FWOBidSection { get; set; }
}
public class ConditionalJoin
{
public bool jOpt1 { get; set; }
public bool jOpt2 { get; set; }
public ConditionalJoin(bool _joinOption1, bool _joinOption2)
{
jOpt1 = _joinOption1;
jOpt2 = _joinOption2;
}
public class FBandSo
{
public Bids FWOBids { get; set; }
public SellingOptions FWOSellingOptions { get; set; }
}
public class FBandI
{
public Bids FWOBids { get; set; }
public Item FWOItem { get; set; }
}
public void Run()
{
var fwoBids = new List<Bids>();
var sellingOptions = new List<SellingOptions>();
var fwoItems = new List<Item>();
fwoBids.Add(new Bids() { Id = 1, Price = 1.5 });
sellingOptions.Add(new SellingOptions() { BidId = 1, Quantity = 2 });
fwoItems.Add(new Item() { ItemId = 10, FWOBidSection = new BidSection() { BidId = 1 } });
IQueryable<Bids> fb = fwoBids.AsQueryable();
IQueryable<SellingOptions> so = sellingOptions.AsQueryable();
IQueryable<Item> i = fwoItems.AsQueryable();
IQueryable<FBandSo> FBandSo = null;
IQueryable<FBandI> FBandI = null;
if (jOpt1)
{
FBandSo = from f in fb
join s in so on f.Id equals s.BidId
select new FBandSo()
{
FWOBids = f,
FWOSellingOptions = s
};
}
if (jOpt2)
{
FBandI = from f in fb
join y in i on f.Id equals y.FWOBidSection.BidId
select new FBandI()
{
FWOBids = f,
FWOItem = y
};
}
if (jOpt1 && jOpt2)
{
var query = from j1 in FBandSo
join j2 in FBandI
on j1.FWOBids.Id equals j2.FWOItem.FWOBidSection.BidId
select new
{
FWOBids = j1.FWOBids,
FWOSellingOptions = j1.FWOSellingOptions,
FWOItems = j2.FWOItem
};
}
}
}
My Class
public partial class CTITLE_CHECKLIST : CError
{
public int Id { get; set; }
[Required(ErrorMessage = "Requerido")]
public int ID_Tipo_Checklist { get; set; }
[Required(ErrorMessage = "Requerido")]
public string Descripcion { get; set; }
public virtual CTipo_CheckList Tipo_CheckList { get; set; }
public ICollection<CSUBTITLE_CHECKLIST> Subtitulos { get; set; }
}
My method :
public List<CTITLE_CHECKLIST> GetCheked(string codigo, int tipoCheckList)
{
try
{
var result = (from a in db.TITLE_CHECKLIST
from t in db.Tipo_CheckList
where a.ID_Tipo_Checklist == t.ID
where a.ID_Tipo_Checklist == tipoCheckList
select new CTITLE_CHECKLIST
{
Descripcion = a.Descripcion,
Id = a.Id,
ID_Tipo_Checklist = a.ID_Tipo_Checklist,
Tipo_CheckList = new CTipo_CheckList
{
Descripcion = t.Descripcion,
ID = t.ID,
ID_Depto = t.ID_Depto
},
Subtitulos = (from s in db.SUBTITLE_CHECKLIST
where s.ID_Title == a.Id
select new CSUBTITLE_CHECKLIST
{
AmountCK = s.AmountCK,
Descripcion = s.Descripcion,
ID = s.ID,
ID_Title = s.ID_Title,
Numeracion = s.Numeracion,
checkList = (from ck in db.CheckList
where ck.ID_Subtitle == s.ID
&& ck.Codigo == codigo
select new CCheckList
{
CK = ck.CK,
Amount = ck.Amount,
Codigo = ck.Codigo,
Codigo_TFile = ck.Codigo_TFile,
Comentario = ck.Comentario,
ID = ck.ID,
ID_Subtitle = ck.ID_Subtitle,
UserCre = ck.UserCre,
UserMod = ck.UserMod
}).FirstOrDefault()
})//here I put ToList
}).ToList();
An my error this :
Error 2 Cannot implicitly convert type 'System.Linq.IQueryable<TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST>' to 'System.Collections.Generic.ICollection<TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST>'. An explicit conversion exists (are you missing a cast?) C:\Users\jmitchell\Documents\Visual Studio 2012\Projects\TROP\TROP\Areas\TRAFICO\Controllers\LOGICA\CTITLE_CHECKLIST.cs 136 49 TROP
And When I put .ToList, where say Here I put ToList it throw an error that say :
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST] ToList[CSUBTITLE_CHECKLIST](System.Collections.Generic.IEnumerable`1[TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST])' method, and this method cannot be translated into a store expression.
And I Know that if I change the property subtitles to IEnumerable<T> it will work, but, Im trying to bind this model from MVC4 post, And I doesn't bind with IEnumerable<T>, it bind with a ICollection<T>, List<T> , I am like 1 and a half day trying to figure out this problem.
So the choices are not "do the whole thing in the database" or "do the whole thing in memory". You want to do some of both. Do everything on the DB end that you can, and then when you've done all of that, finish up the remaining operations in memory. This general pattern (mostly leveraging AsEnumerable) will allow you to do this:
(from a in db.TITLE_CHECKLIST
from t in db.Tipo_CheckList
where a.ID_Tipo_Checklist == t.ID
where a.ID_Tipo_Checklist == tipoCheckList
select new //note were using an anonymous type here,
//as the real type can't take a non-list
{
Descripcion = a.Descripcion,
Id = a.Id,
ID_Tipo_Checklist = a.ID_Tipo_Checklist,
Tipo_CheckList = new CTipo_CheckList
{
Descripcion = t.Descripcion,
ID = t.ID,
ID_Depto = t.ID_Depto
},
Subtitulos = from s in db.SUBTITLE_CHECKLIST
where s.ID_Title == a.Id
select new CSUBTITLE_CHECKLIST
{
AmountCK = s.AmountCK,
Descripcion = s.Descripcion,
ID = s.ID,
ID_Title = s.ID_Title,
Numeracion = s.Numeracion,
checkList = (from ck in db.CheckList
where ck.ID_Subtitle == s.ID
&& ck.Codigo == codigo
select new CCheckList
{
CK = ck.CK,
Amount = ck.Amount,
Codigo = ck.Codigo,
Codigo_TFile = ck.Codigo_TFile,
Comentario = ck.Comentario,
ID = ck.ID,
ID_Subtitle = ck.ID_Subtitle,
UserCre = ck.UserCre,
UserMod = ck.UserMod
}).FirstOrDefault()
}//note no ToList
})
//This will ensure that all operators that follow
//are done in memory, not on the DB end
.AsEnumerable()
.Select(checklist => new CTITLE_CHECKLIST
{
Descripcion = checklist.Descripcion,
Id = checklist.Id,
ID_Tipo_Checklist = checklist.ID_Tipo_Checklist,
Subtitulos = Subtitulos.ToList(),
});