How do I fill a child list inside a parent list using linq2db in a single query in my .net core app? - c#

I am trying to query my database to return turn reports with any attachments included. I need a list of turn report items which are returned by date, and then for each report I want it to also return all of the attachments associated with the turn reports. The only way to associate them is by the EntryId.
Here is my method to get the turn reports:
public List<TurnReportItem> GetTurnReportsByDateShiftAndDept(DateTime shiftStart, int shiftNum, int dept)
{
try
{
List<TurnReportItem> list;
using (connection)
{
list = (from r in connection.VTurnReports
join a in connection.TurnReportAreas on r.AreaId equals a.AreaId
where a.DeptId == dept && a.Enabled && r.ShiftDate == shiftStart && r.ShiftNum == shiftNum
select new TurnReportItem
{
areaId = r.AreaId,
areaName = a.Name,
author = r.Author,
comment = r.Comment,
datetime = r.Datetime,
id = r.EntryId,
ip = r.Ip,
shiftDate = r.ShiftDate,
shiftNum = r.ShiftNum,
sort_order = a.SortOrder,
attachment_count = r.AttachmentCount,
attachments = (
from at in connection.TurnReportAttachments where at.EntryId == r.EntryId
select new TurnReportAttachment
{
AttachmentId = at.AttachmentId,
FileName = at.FileName
}).ToList()
})
.OrderBy(r => r.sort_order)
.OrderBy(r => r.datetime)
.ToList();
return list;
}
}
Here is the TurnReportItem class that I am filling. If I do not have the subquery I do get all of the turnreports.
public class TurnReportItem
{
public int id;
public string comment;
public DateTime datetime;
public string author;
public int areaId;
public string areaName;
public DateTime shiftDate;
public int shiftNum;
public string ip;
public int? attachment_count;
public int sort_order;
public int area_rating;
public List<TurnReportAttachment> attachments;
public TurnReportItem() { }
}
I have a separate method that will return the all of the comments with the entry id. I have tried to fill the list using that method. I am converting this from a MVC app and I was able to use the method to fill the list however it will not work when I try it in this app, I also would prefer to only make one connection in the database to get what I need.
List<TurnReportItem> list;
using (connection)
{
list = (from r in connection.VTurnReports
join a in connection.TurnReportAreas on r.AreaId equals a.AreaId
where a.DeptId == dept && a.Enabled && r.ShiftDate == shiftStart && r.ShiftNum == shiftNum
select new TurnReportItem
{
areaId = r.AreaId,
areaName = a.Name,
author = r.Author,
comment = r.Comment,
datetime = r.Datetime,
id = r.EntryId,
ip = r.Ip,
shiftDate = r.ShiftDate,
shiftNum = r.ShiftNum,
sort_order = a.SortOrder,
attachment_count = r.AttachmentCount,
attachments = SelectAttachmentsByEntryId(r.EntryId)
})
.OrderBy(r => r.sort_order)
.OrderBy(r => r.datetime)
.ToList();
return list;
}
public List<TurnReportAttachment> SelectAttachmentsByEntryId(int EntryId)
{
using (connection)
{
// we do it this way so that we don't return the blob
var results = from p in connection.TurnReportAttachments
where p.EntryId == EntryId
select new TurnReportAttachment
{
EntryId = p.EntryId,
AttachmentId = p.AttachmentId,
FileName = p.FileName
};
return results.ToList();
}
}

In your case SelectAttachmentsByEntryId should be static, with additional parameter connection. To make it work, it is needed to use ExpressionMethod.
public static class ReportHelpers
{
[ExpressionMethod(nameof(SelectAttachmentsByEntryIdImpl))]
public static List<TurnReportAttachment> SelectAttachmentsByEntryId(MyConnection connection, int EntryId)
{
throw new InvalidOperationException(); // should never enter here
}
private static Expression<Func<MyConnection, int, List<TurnReportAttachment>>> SelectAttachmentsByEntryIdImpl()
{
return (connection, EntryId) =>
(from p in connection.TurnReportAttachments
where p.EntryId == EntryId
select new TurnReportAttachment
{
EntryId = p.EntryId,
AttachmentId = p.AttachmentId,
FileName = p.FileName
})
.ToList();
}
}
Then you can use this method in queries:
public List<TurnReportItem> GetTurnReportsByDateShiftAndDept(DateTime shiftStart, int shiftNum, int dept)
{
using (connection)
{
var list = (from r in connection.VTurnReports
join a in connection.TurnReportAreas on r.AreaId equals a.AreaId
where a.DeptId == dept && a.Enabled && r.ShiftDate == shiftStart && r.ShiftNum == shiftNum
select new TurnReportItem
{
areaId = r.AreaId,
areaName = a.Name,
author = r.Author,
comment = r.Comment,
datetime = r.Datetime,
id = r.EntryId,
ip = r.Ip,
shiftDate = r.ShiftDate,
shiftNum = r.ShiftNum,
sort_order = a.SortOrder,
attachment_count = r.AttachmentCount,
attachments = ReportHelpers.SelectAttachmentsByEntryId(connection, r.EntryId)
})
.OrderBy(r => r.sort_order)
.ThenBy(r => r.datetime)
.ToList();
return list;
}
}
Note that OrderBy.OrderBy has no sense. It should be OrderBy.ThenBy

Related

C# - String to list used in Linq Where Any statement

I would like to use this string as a filter to remove some Ids in a linq query
public class ProductKitMakerDto
{
public int Id { get; set; }
public string TitleShort { get; set; }
public string Media { get; set; }
}
[HttpPost]
public ActionResult KitItemSelect(string culture)
{
string productMakerIds = "4174,2196,2201,2460,2508,2204";
//create a list
var productMakerList = new List<ProductKitMakerDto>();
foreach (int i in productMakerIds)
{
productMakerList.Add(new ProductKitMakerDto { Id = i });
}
var itemselects = (from p in _context.Products
where p.Matrix == 2400
select new ProductKitMakerDto()
{
Id = p.Id,
TitleShort = culture == "de" ? p.TitleShortDe :
culture == "fr" ? p.TitleShortFr :
p.TitleShortEn,
Media = "/img/" + p.Photo,
}).ToList();
//From this query I get 40 results.
//Then I want to remove the ones from the list:
//itemselects = itemselects.Where(i => !productMakerList.Any(pml =>pml.Id == i.Id));
//1st (above) I get an Error CS0266 asking for explicit cast. So aplly the modification
itemselects = (List<ProductKitMakerDto>)itemselects.Where(i => !productMakerList.Any(pml =>pml.Id == i.Id));
return Json(itemselects, JsonRequestBehavior.AllowGet);
}
I get 500 (Internal Server Error) - xhr.send( options.hasContent && options.data || null );
I guess the list is empty.
Any idea? Thanks
this does not work
string productMakerIds = "4174,2196,2201,2460,2508,2204";
var productMakerList = new List<ProductKitMakerDto>();
foreach (int i in productMakerIds)
{
productMakerList.Add(new ProductKitMakerDto { Id = i });
}
because you need to split on comma first and parse the string to int:
foreach (string i in productMakerIds.Split(',')) // and parse i to int with int.Parse
but since it's a string literal, initialize it correctly in the first place. Don't use a List<ProductKitMakerDto> because you just need a List<int>, then you can use Contains:
var productMakerList = new List<int>
{
4174, 2196, 2201, 2460, 2508 , 2204
};
you can not cast to a list if it's not a list and Enumerable.Where does not return one:
itemselects = (List<ProductKitMakerDto>)itemselects.Where(i => !productMakerList.Any(pml =>pml.Id == i.Id));
you need to append ToList after the Where
itemselects = itemselects
.Where(i => !productMakerList.Any(pml =>pml.Id == i.Id))
.ToList();
but as mentioned, you could also use this Where before you create that list the first time, so include the condition witha Contains which should be supported:
var itemselects = (from p in _context.Products
where p.Matrix == 2400
&& !productMakerList.Contains(p.Id)
select new ProductKitMakerDto()
{
Id = p.Id,
TitleShort = culture == "de"
? p.TitleShortDe
: culture == "fr" ? p.TitleShortFr : p.TitleShortEn,
Media = "/img/" + p.Photo,
}).ToList();
foreach (string i in productMakerIds.Split(','))
{
productMakerList.Add(new ProductKitMakerDto { Id = int.Parse(i) });
}

EF: How to pass column name dynamically to where clause

i am not before dev pc. i just started working with EF. so curious to know can we pass column name dynamically for where clause.
see a screen shot for searching grid.
i just compose a sample query. please tell me does it work?
public ActionResult Index(String ColumnName,String SearchText)
{
private CustomersEntities db = new CustomersEntities();
var customer = (from s in db.Customers
select new CustomerDTO
{
CustomerID = s.CustomerID,
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address
})
.Where(s => s.Field<string>(ColumnName).ToUpper().Contains(SearchText.ToUpper());
return View(customer);
}
thanks
public ActionResult Index(string ColumnName, string SearchText)
{
var arg = Expression.Parameter(typeof(Customer), "x");
var strType = typeof(string);
var ToUpperMeth = strType.GetMethods().Where(x => x.Name == nameof(string.ToUpper)
&& x.GetParameters().Count() == 0).Single();
var ContainsMeth = strType.GetMethods().Where(x => x.Name == nameof(string.Contains)
&& x.GetParameters().Count() == 1).Single();
var exprVal = Expression.Constant(SearchText);
var toUpExprVal = Expression.Call(exprVal, ToUpperMeth);
var exprProp = Expression.Property(arg, ColumnName);
var toUpExpr = Expression.Call(exprProp, ToUpperMeth);
var contExpr = Expression.Call(toUpExpr, ContainsMeth, toUpExprVal);
var predicate = Expression.Lambda<Func<Customer, bool>>(contExpr, arg);
var customer = (from s in db.Customers
select new CustomerDTO
{
CustomerID = s.CustomerID,
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address
}).Where(predicate).ToList();
return View(customer);
}
You can create something like this in repository (if you use it)
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return _context.Set<CustomersEntities>().Where(predicate);
}
and then
var result = _repository.FindBy(y => y.CompanyName.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0);
The basic pattern is to build up the query at runtime, selectively adding Where expressions before running the query and projecting the results into the DTO.
Like this:
public IList<CustomerDTO> FindCustomers(String ColumnName, String SearchText)
{
var query = from s in db.Customers select s;
if (ColumnName == "CompanyName")
{
query = query.Where(c => c.CompanyName == SearchText);
}
else if (ColumnName == "ContactName")
{
query = query.Where(c => c.ContactName == SearchText);
}
//. . .
else
{
throw new InvalidOperationException($"Column {ColumnName} not found or not supported for searching.");
}
var results = from c in query
select new CustomerDTO()
{
CustomerID = c.CustomerID,
CompanyName = c.CompanyName,
ContactName = c.ContactName,
ContactTitle = c.ContactTitle,
Address = c.Address
};
return results;
}

Linq where clause using filter object

I have a piece of Linq that queries an EntityFramework context in my web controller and returns the result, as follows:
[HttpGet]
public IActionResult GetRoutingRules()
{
var query = (from rr in _context.RoutingRules
join dest in _context.RoutingZones on rr.DestinationZoneId equals dest.ZoneId
join origin in _context.RoutingZones on rr.OriginZoneId equals origin.ZoneId
join hub in _context.RoutingHub on rr.HubId equals hub.HubId
select new RoutingRulesDto(rr) { DestinationZoneName = dest.ZoneName, OriginZoneName = origin.ZoneName, HubName = hub.HubName });
return Ok(query);
}
I want a new method that will take a "filter" object, where I can narrow down the results of the above. My filter object looks like this:
public class RoutingSearchFilterDto
{
public int BrandId { get; set; }
public int? ServiceType { get; set; }
public long? OriginZoneId { get; set; }
public long? DestinationZoneId { get; set; }
public int? RuleRanking { get; set; }
public bool? IsRuleActive { get; set; }
}
The minimum info that needs to be set in this class is BrandId. All other properties are options in the filter.
I need to write a new controller method that will utilise this, something like:
[HttpPost("filtered")]
public IActionResult GetFilteredRoutingRules([FromBody] RoutingSearchFilterDto filter)
{
...
}
How do I linq query on properties that could potentially be null? Essentially, a dynamic query depending on the properties set in the filter object.
NOTE: I want this to affect the select statement that the EF runs, not just let EF get all the data, then filter the data set - the point of this is to make the db call more efficient.
Filter object might be sent where BrandId = 1, IsRuleActive = 1. Equally, it could be BrandId = 1, ServiceType = 3 (and therefore IsRuleActive is null so shouldn't be in the linq where clause).
I've tried this:
var param = (Expression.Parameter(typeof(RoutingRules), "rr"));
Expression combinedExpr = null;
if (filter.BrandId != null)
{
var exp = Expression.Equal(Expression.Property(param, "BrandId"), Expression.Constant(filter.BrandId));
combinedExpr = exp;
}
if (filter.DestinationZoneId != null)
{
var exp = Expression.Equal(Expression.Property(param, "DestinationZoneId"), Expression.Constant(filter.DestinationZoneId));
combinedExpr = (combinedExpr == null ? exp : Expression.AndAlso(combinedExpr, exp));
}
if (filter.OriginZoneId != null)
{
var exp = Expression.Equal(Expression.Property(param, "OriginZoneId"), Expression.Constant(filter.OriginZoneId));
combinedExpr = (combinedExpr == null ? exp : Expression.AndAlso(combinedExpr, exp));
}
if (filter.EshopServiceType != null)
{
var exp = Expression.Equal(Expression.Property(param, "EshopServiceType"), Expression.Constant(filter.EshopServiceType));
combinedExpr = (combinedExpr == null ? exp : Expression.AndAlso(combinedExpr, exp));
}
if (filter.IsRuleActive != null)
{
var exp = Expression.Equal(Expression.Property(param, "IsRuleActive"), Expression.Constant(filter.IsRuleActive, typeof(bool?)));
combinedExpr = (combinedExpr == null ? exp : Expression.AndAlso(combinedExpr, exp));
}
if (filter.RuleRanking != null)
{
var exp = Expression.Equal(Expression.Property(param, "RuleRanking"), Expression.Constant(filter.RuleRanking));
combinedExpr = (combinedExpr == null ? exp : Expression.AndAlso(combinedExpr, exp));
}
if (combinedExpr == null)
combinedExpr = Expression.Default(typeof(bool));
var compiled = Expression.Lambda<Func<RoutingRules, bool>>(combinedExpr, param).Compile();
var results = (from rr in _context.RoutingRules.Where(compiled)
join dest in _context.RoutingZones on rr.DestinationZoneId equals dest.ZoneId
join origin in _context.RoutingZones on rr.OriginZoneId equals origin.ZoneId
join hub in _context.RoutingHub on rr.HubId equals hub.HubId
where rr.BrandId == 21
select new RoutingRulesDto(rr) { DestinationZoneName = dest.ZoneName, OriginZoneName = origin.ZoneName, HubName = hub.HubName });
But the Where clause isn't applied to the generated Sql, it seems to pull back all records, then apply the where in memory, which isn't what I need.
Thanks in advance for any pointers!!
You can build an expression tree for this, but have you considered:
IQueryable<...> query = ...;
if (routingSearchFilter.ServiceType != null)
query = query.Where(e => e.ServiceType == routingSearchFilter.ServiceType);
if (...)
query = query.Where(....);
The EF engine is smart enough to combine the Where clauses (with AND of course).
Edit:
It wasn't clear if you wanted to filter on the joined result or only on the first table. In that case it would continue like
var result = (from rr in query
join dest in _context.RoutingZones on rr.DestinationZoneId equals dest.ZoneId
join ...
select new RoutingRulesDto(rr) .... ).ToSometing();
But I'm a little wary about that RoutingRulesDto(rr) constructor parameter.
If you use the fluent API for LINQ, you can conditionally add Where clauses.
var query = _content.RoutingRules.Where(r => r.BrandId == filter.BrandId);
if (filter.OriginZoneId != null) {
query = query.Where(r => r.OriginZoneId == filter.OriginZoneId);
}
if (filter.EshopServiceType != null) {
query = query.Where(r => r.EshopServiceType == filter.EshopServiceType);
}
// etc...
var result = query.ToArray();
Just to have my final solution in black and white, here's what I had in the end:
[HttpPost("filtered")]
public IActionResult GetFilteredRoutingRules([FromBody] RoutingSearchFilterDto filter)
{
// Query to be build on the routing rules table.
IQueryable<RoutingRules> query = _context.RoutingRules;
// Populate the linked foreign key entities.
query.Include(x => x.Hub).Include(y => y.DestinationZone).Include(z => z.OriginZone);
// Build dynamic where statements.
if (filter.BrandId != null)
query = query.Where(r => r.BrandId == filter.BrandId);
if (filter.OriginZoneId != null)
query = query.Where(r => r.OriginZoneId == filter.OriginZoneId);
if (filter.DestinationZoneId != null)
query = query.Where(r => r.DestinationZoneId == filter.DestinationZoneId);
if (filter.IsRuleActive != null)
query = query.Where(r => r.IsRuleActive == filter.IsRuleActive);
if (filter.RuleRanking != null)
query = query.Where(r => r.RuleRanking == filter.RuleRanking);
// If you want to add paging:
query = query.Skip(filter.PageSize * filter.PageNumber).Take(filter.PageSize);
// Perform select on the table and map the results.
var result = query.Select(r => new RoutingRulesDto
{
RoutingRuleId = r.RoutingRuleId,
BrandId = r.BrandId,
LastMileCarrierCode = r.LastMileCarrierCode,
CashOnDelivery = r.CashOnDelivery,
CreationTime = r.CreationTime,
CurrencyCode = r.CurrencyCode,
CurrencyDescription = Enum.Parse(typeof(Enumerations.CurrencyCode), r.CurrencyCode),
DestinationZoneId = r.DestinationZoneId,
EddFromDay = r.EddFromDay,
EddToDay = r.EddToDay,
ServiceType = r.ServiceType,
ServiceTypeName = Enum.Parse(typeof(Enumerations.ServiceType), r.EshopServiceType),
IsPickUpAvailable = r.IsPickUpAvailable,
LastUpdateTime = r.LastUpdateTime,
LastUpdateUser = r.LastUpdateUser,
OriginZoneId = r.OriginZoneId,
RuleRanking = r.RuleRanking,
SignOnDelivery = r.SignOnDelivery,
TermsOfDelivery = r.TermsOfDelivery,
TermsOfDeliveryName = Enum.Parse(typeof(Enumerations.TermsOfDelivery), r.TermsOfDelivery),
ValueOfGoods = r.ValueOfGoods,
WeightLowerLimit = r.WeightLowerLimit,
WeightUpperLimit = r.WeightUpperLimit,
FirstMileCarrierCode = r.FirstMileCarrierCode,
HubId = r.HubId,
IsInsuranceAvailable = r.IsInsuranceAvailable,
IsRuleActive = r.IsRuleActive,
HubName = r.Hub.HubName,
DestinationZoneName = r.DestinationZone.ZoneName,
OriginZoneName = r.OriginZone.ZoneName,
});
// The SQL produced includes the joins and where clauses as well as only
// selecting the column names that are required in the flattened return object.
return Ok(result);
}
Thanks for the help guys!

Insert new rows based on date in Entity framework

I have been handed over an application that uses entity framework. I'm not familiar with entity and I'm having an issue that I can't figure out. This application was made to migrate data from a database to a more relational database. After the initial migration, we have to run it again to insert additional rows that were not part of the original migration. (There is a 3 week gap). I know that I have to put a check in and I want to do this by one of the columns we uses named "DateChanged" but unfortunately I'm not sure how to do this in entity. This is my first effort and it just shows in red which is depressing. I have searched on the internet but have found no solutions.
if (!newData.tVehicleLogs.Any(v => v.DateChanged.Value.ToShortDateString("6/27/2014")))//I'm not sure how to check the DateChanged here.
{
newData.tVehicleLogs.Add(deal);
comment = new tVehicleComment
{
Comment = vehicle.Reason,
DealID = deal.DealID,
CurrentComment = false
};
newData.tVehicleComments.Add(comment);
newData.SaveChanges();
int cId = comment.CommentID;
deal.CommentID = cId;
}
}
So as you can see I'm trying to check the date with the if statement, but I can't get the syntax correct... after trying everything I know to try .. which isn't much at this point.
I basically need to check if the DateChanged is from 6/27/2014 to today's date. If it's before then, then it has already been migrated over and doesn't need migrated over again. Where it says comment, if the row is new, then it inserts the old comment into the new comments table, then updates the tVehicleLogs table with the commentID. I'm just stuck on the date checking part. Any help is greatly appreciated!!
EDIT: This is the entire code for inserting the into tVehicleLogs..
if (MigrateLogs)
{
List<VLog> vlog = oldData.VLogs.ToList();
foreach (VLog vehicle in vlog)
{
tBank bank;
tCustomer cust;
tFIManager manag;
tSalesPerson sales;
tMake make;
tModel model;
tDealership dealership;
tMakeDealership makedeal;
tVehicleComment comment;
tInternalLocation location;
string dealershipName = getProperDealershipName(vehicle.Dealership, newData);
bank = (newData.tBanks.Any(banks => banks.BankName == vehicle.BankName) ? newData.tBanks.Where(b => b.BankName == vehicle.BankName).FirstOrDefault() : newData.tBanks.Add(new tBank { BankName = vehicle.BankName }));
cust = (newData.tCustomers.Any(customer => customer.CustomerNumber == vehicle.CustNumber) ? newData.tCustomers.Where(customer => customer.CustomerNumber == vehicle.CustNumber).FirstOrDefault() : newData.tCustomers.Add(new tCustomer { CustomerNumber = vehicle.CustNumber, CustomerName = vehicle.Buyer }));
//cust = (newData.tCustomers.Any(customer => customer.CustomerNumber == vehicle.CustNumber && customer.CustomerName == vehicle.CustNumber) ? newData.tCustomers.Where(customer => customer.CustomerNumber == vehicle.CustNumber).FirstOrDefault() : newData.tCustomers.Add(new tCustomer { CustomerNumber = vehicle.CustNumber, CustomerName = vehicle.Buyer }));
manag = (newData.tFIManagers.Any(manager => manager.FIName == vehicle.FIName) ? newData.tFIManagers.Where(manager => manager.FIName == vehicle.FIName).FirstOrDefault() : newData.tFIManagers.Add(new tFIManager { FIName = vehicle.FIName }));
sales = (newData.tSalesPersons.Any(person => person.SalesPersonNumber == vehicle.SalesPerson) ? newData.tSalesPersons.Where(person => person.SalesPersonNumber == vehicle.SalesPerson).FirstOrDefault() : newData.tSalesPersons.Add(new tSalesPerson { SalesPersonNumber = vehicle.SalesPerson }));
make = (newData.tMakes.Any(m => m.Make == vehicle.Make) ? newData.tMakes.Where(m => m.Make == vehicle.Make).FirstOrDefault() : newData.tMakes.Add(new tMake { Make = vehicle.Make }));
model = (newData.tModels.Any(m => m.Model == vehicle.Model) ? newData.tModels.Where(m => m.Model == vehicle.Model).FirstOrDefault() : newData.tModels.Add(new tModel { Model = vehicle.Model, MakeID = make.MakeID }));
dealership = (newData.tDealerships.Any(d => d.DealershipName == dealershipName) ? newData.tDealerships.Where(d => d.DealershipName == dealershipName).FirstOrDefault() : newData.tDealerships.Add(new tDealership { DealershipName = dealershipName }));
makedeal = (newData.tMakeDealerships.Any(d => d.MakeID == make.MakeID && d.DealershipID == dealership.DealershipID) ? newData.tMakeDealerships.Where(d => d.MakeID == make.MakeID && d.DealershipID == dealership.DealershipID).FirstOrDefault() : newData.tMakeDealerships.Add(new tMakeDealership { DealershipID = dealership.DealershipID, MakeID = make.MakeID }));
location = (newData.tInternalLocations.Any(l => l.LocationName == vehicle.Location) ? newData.tInternalLocations.Where(l => l.LocationName == vehicle.Location).FirstOrDefault() : newData.tInternalLocations.Add(new tInternalLocation { LocationName = vehicle.Location }));
//log = (newData.tVehicleLogs.Any(l => l.DealNumber == vehicle.FIMAST &&) ? newData.tVehicleLogs.Where(l => l.DealNumber == vehicle.FIMAST).FirstOrDefault() : newData.tVehicleLogs.Add(new tVehicleLog {DealNumber = vehicle.FIMAST }));
Int32 stat;
int? status;
if (Int32.TryParse(vehicle.Status, out stat))
status = stat;
else
status = null;
DateTime titled, bounced, dateReceived;
bool trueTitled = DateTime.TryParse(vehicle.Titled, out titled);
bool trueBounced = DateTime.TryParse(vehicle.Bounced, out bounced);
bool trueReceived = DateTime.TryParse(vehicle.DateReceived, out dateReceived);
int dealid = newData.tVehicleDeals.Where(v => v.DealNumber == vehicle.FIMAST).FirstOrDefault().DealID;
tVehicleLog deal = new tVehicleLog
{
DealNumber = vehicle.FIMAST,
StockNumber = vehicle.StockNumber,
BankID = bank.BankID,
CustomerID = cust.CustomerID,
FIManagerID = manag.FIManagerID,
SalesPersonID = sales.SalesPersonID,
VINNumber = null,
DealDate = vehicle.DealDate,
NewUsed = vehicle.NewUsed,
GrossProfit = vehicle.GrossProfit,
AmtFinanced = vehicle.AmtFinanced,
CloseDate = null,
Category = vehicle.RetailLease,
Status = status,
DealershipID = dealership.DealershipID,
NewDeal = false,
Archived = false,
InternalLocationID = location.InternalLocationID,
ChangedBy = vehicle.ChangedBy,
DateChanged = DateTime.Parse(vehicle.DateChanged),
Titled = null,
Bounced = null,
MakeID = make.MakeID,
ModelID = model.ModelID,
DealID = dealid,
CommentID = null
};
if (trueTitled)
deal.Titled = titled;
if (trueBounced)
deal.Bounced = bounced;
if (trueReceived)
deal.DateReceived = dateReceived;
DateTime targetDate = new DateTime(2014, 06, 27);
//if(!newData.tVehicleLogs.Any(v => v.DateChanged >= targetDate))
if(deal.DateChanged >= targetDate && !newData.tVehicleLogs.Any(v => v.DateChanged >= targetDate))
{
newData.tVehicleLogs.Add(deal);
comment = new tVehicleComment
{
Comment = vehicle.Reason,
DealID = deal.DealID,
CurrentComment = false
};
newData.tVehicleComments.Add(comment);
newData.SaveChanges();
int cId = comment.CommentID;
deal.CommentID = cId;
}
}
}
I don't think you need to use linq here (providing you've pulled the object down). Just check the dates.
// pull down the object
var deal = newData.tVehicleLogs.Where(v => v.Id == SOMEID).FirstOrDefault();
DateTime targetDate = new DateTime(2014,06,27);
if (tVehicleLogs.DateChaned <= DateTime.Now
&& tVehicleLogs.DateChaned >= targetDate) {
}
Alternatively, pull down all the objects that meet the date criteria and foreach over them.
List<YourObject> list = newData.tVehicleLogs.Where(v => v.DateChanged <= DateTime.Now
&& v.DateChanged >= targetDate).ToList();
foreach(var l in list) {
// do your stuff here
}

Is there a better way to do this Linq query and function?

I'm making this method retrieve records from the Data Base. As you can see I want to return a List<ITieneID> where ITieneID is an Interface defined on my business layer.
AtlasWFM_Entities.Clases.Area implements that interface. It is pretty clear that this is not a good way to accomplishing it. Here's the code:
public override List<ITieneID> Buscar(ITieneID elementoPatron)
{
List<ITieneID> result = new List<ITieneID>();
var resultado = from a in base.Repository.Context.Areas
where a.areaID.Equals(elementoPatron.ID) || a.areaDescripcion.Contains(elementoPatron.Descripcion)
select new AtlasWFM_Entities.Clases.Area
{
ID = a.areaID,
Descripcion = a.areaDescripcion,
Estado = a.areaEstado,
};
foreach (var r in resultado)
{
ITieneID t = new AtlasWFM_Entities.Clases.Area
{
ID = r.ID,
Descripcion = r.Descripcion,
Estado = r.Estado,
};
result.Add(t);
}
return result;
}
Any Ideas how to improve this?
public override List<ITieneID> Buscar(ITieneID elementoPatron)
{
var resultado = from a in base.Repository.Context.Areas
where a.areaID.Equals(elementoPatron.ID) || a.areaDescripcion.Contains(elementoPatron.Descripcion)
select new AtlasWFM_Entities.Clases.Area
{
ID = a.areaID,
Descripcion = a.areaDescripcion,
Estado = a.areaEstado,
};
return new List<ITieneID>(resultado);
}
UPDATE: That don't compile, but this should:
return new List<ITieneID>(resultado.Cast<ITieneID>());
In fact, I think you can reduce the whole thing to:
public override List<ITieneID> Buscar(ITieneID elementoPatron)
{
var resultado = from a in base.Repository.Context.Areas
where a.areaID == elementoPatron.ID || a.areaDescripcion.Contains(elementoPatron.Descripcion)
select a;
return new List<ITieneID>(resultado.Cast<ITieneID>());
}
of a little more concise:
public override List<ITieneID> Buscar(ITieneID elementoPatron)
{
return new List<ITieneID>(base.Repository.Context.Areas
.Where(a=>a.areaID == elementoPatron.ID || a.areaDescripcion.Contains(elementoPatron.Descripcion))
.Cast<ITieneID>());
}
Well, if you need to do this in two "hops" in order to work around any LINQ to SQL limitations, you could use LINQ to SQL and then LINQ to Objects:
var resultado = from a in base.Repository.Context.Areas
where a.areaID.Equals(elementoPatron.ID) ||
a.areaDescripcion.Contains(elementoPatron.Descripcion)
select new AtlasWFM_Entities.Clases.Area
{
ID = a.areaID,
Descripcion = a.areaDescripcion,
Estado = a.areaEstado,
};
return resultado.AsEnumerable() // Do the rest in LINQ to objects
.Select(r => new AtlasWFM_Entities.Clases.Area
{
ID = r.ID,
Descripcion = r.Descripcion,
Estado = r.Estado,
})
.ToList();
If Area implements the ITieneID interface just do
var resultado = from a in base.Repository.Context.Areas
where a.areaID.Equals(elementoPatron.ID) || a.areaDescripcion.Contains(elementoPatron.Descripcion)
select new AtlasWFM_Entities.Clases.Area
{
ID = a.areaID,
Descripcion = a.areaDescripcion,
Estado = a.areaEstado,
};
result = resultado.ToList().ConvertAll(x=> x as ITieneID);
return result;

Categories

Resources