I am facing a problem when try to update records via using dbset.
The following is my code:
CROPContext db = new CROPContext();
var EPins = from EPin in db.Pins.Take(5)
where
(EPin.UserID == null && EPin.CC == 5000)
select EPin;
foreach (var item in Epins.ToList())
{
item.OrderID = OrderID;
item.UserID = intUserID;
}
db.SaveChanges();
When I update the records, it update all records.
Then I check the number EPins.Count(), I find out that it is not 5 but the number of all.
If I want to update the first 5 records, what should I do?
var EPins = (from EPin in db.Pins
where
(EPin.UserID == null && EPin.CC == 5000)
select EPin).Take(5);
foreach (var item in Epins.ToList())
{
item.OrderID = OrderID;
item.UserID = intUserID;
}
db.SaveChanges();
Try the above
db.Pins.Where(EPin => EPin.UserID == null && EPin.CC == 5000).Take(5).ToList()
.ForEach( item => { item.OrderID = OrderID; item.UserID = intUserID; });
db.SaveChanges();
If you using EF6 then you can use EntityFramework.Extended:
db.Pins.Where(EPin => EPin.UserID == null && EPin.CC == 5000)
.Update(p => new Pin { OrderID = OrderID; UserID = intUserID; });
Avoid using .ForEach because of performance implications, stream the data rather than materialise it
Related
I would like to loop through a list of item,
find the matching record in another list and
check a property of that item in the new list is enabled/disabled.
if false, break the looping.
Here is my code.
var isDataPresent = true;
foreach (var item in listA)
{
var dataPresent = listB
.FirstOrDefault(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType)
?.IsDataPresent;
if (!dataPresent.GetValueOrDefault())
{
isDataPresent = false;
break;
}
}
return isDataPresent;
Is there a faster/better way to achieve this.
My updated code with JOIN:
var result = listA.Join(listB,
dt => new { dt.Id, dt.DistributionType },
dp => new { dp.Id, dp.DistributionType },
(distType, dataPresent) => new
{
distType.Id,
distType.DistributionType,
dataPresent.IsDataPresent
});
if(result.Any(x => x.IsDataPresent == false))
{
isDataPresent = false;
}
you can change your use of FirstOrDefault() to Any()
that way, you don't need to make other checks and you only need one variable.
var isDataPresent = true;
foreach (var item in listA)
{
isDataPresent = listB.Any(x => x.Id == item.Id &&
x.DistributionType == item.DistributionType && x.IsDataPresent);
if (!isDataPresent)
break;
}
return isDataPresent;
Try with Any like below.
var isDataPresent = !listA.Any(item => !listB
.FirstOrDefault(x => x.Id == item.Id && x.DistributionType == item.DistributionType)
?.IsDataPresent.GetValueOrDefault());
my approach would be .Count()
var countOfA = listA.Count();
var countOfAWithB = listA.Count(a=> listB.Any(b => a.Id == b.Id &&
a.DistributionType == b.DistributionType));
return countOfA == countOfAWithB;
You can achieve by join:
var res = (from dp in dataPresent
from la in listA
where dp.DistributionType == la.DistributionType
select new {
la.isDataPresent }
).ToList()
and there are better solution then join
Can't figure out the logic for Get all records if variable is null else get where officername = officer.
var res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& ((officer != null && h.OfficerName.ToLower() == officer.ToLower()) || ("Get all records"))
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();
While you can make a compound if statement, this will (usually -- currently always) pass this compound statement on to the database. In many cases, this can cause index misses which if done correctly wouldn't be missed. In non-Microsoft SQL servers, these types of queries are also known to just plain not work (MySQL, DB2). It's better to just write the query correctly in the first place:
var query = db.BalanceHistories
.Where(h=>temp.Contains(h.LoanType ?? 0));
if (officer!=null)
{
// Depending on your database, the ToLower()s here may not be needed.
query=query.Where(h=>h.OfficerName.ToLower() == officer.ToLower()))
}
var res=(from h in query
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
});
Just swap ("Get all records") with (officer == null), Although i would suggest you to put this condition at first.
Explanation:
If officer == null than respect to short circut law we will return true and the rest of our condition won't matter.
Else means officer != null and thus we want to check if it matches our h.OfficerName data.
End result:
res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& (
officer == null
|| h.OfficerName.ToLower() == officer.ToLower())
)
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();
Have you tried:
var res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& ((officer == null) || (h.OfficerName.ToLower() == officer.ToLower()))
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();
I use the query below to get all columns(20 more) in Entity Framework Linq. Because of out of memory exception, I only want to get two of them. One is "FileName", the other one is "FilePath". How to modify my code?
var query = DBContext.Table1
.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.FilePath)
.Skip(1000)
.Take(1000)
.ToList();
foreach(var t in query)
{
Console.WriteLine(t.FilePath +"\\"+t.FileName);
}
var query = DBContext.Table1.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.FilePath)
.Skip(1000)
.Take(1000)
.Select(c => new { c.FilePath, c.FileName })
.ToList();
foreach(var t in query)
{
Console.WriteLine(t.FilePath +"\\"+t.FileName);
}
You need to use Select.
Just select out two of the columns:
DBContext.Table1.Select(c => new { c.FileName, c.FilePath });
How about something like
using (var entity = new MyModel(ConnectionString))
{
var query = (from myTable in entity.theTable
where myTable.FacilityID == facilityID &&
myTable.FilePath != null &&
myTable.TimeStationOffHook < oldDate
orderby myTable.FilePath
select new
{
myTable,FileName,
myTable.FilePath
}).Skip(1000).Take(1000).ToList();
//do what you want with the query result here
}
On our online billing application, we give a billing summary of what bills the customer received and the payments they made.
In order for this to work, I have to first pull the payments then match them to the bills. So I have do something like:
foreach (BillPaymentSummary payment in billPayments)
{
DateTime dt = payment.DueDate;
// Debug errors on this next line
var summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL"
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
else
{
summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == payment.DueDate && a.Type == "ADJ "
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
}
}
I have been playing with this, but no matter what I do, I get the following error message:
The entity or complex type 'UtilityBill.Domain.Concrete.BillSummary' cannot be constructed in a LINQ to Entities query.
Is it because I am running queries within queries? How can I get around this error?
I have tried searching Google for an answer and see many answers, but none of them seem to explain my problem.
You cannot project onto a mapped entity. You would have to call ToList() before doing your mapping.
Or better yet, change to the following (calling FirstOrDefault will execute the query and allow you to populate your object):
var summary = db.BillHistories.FirstOrDefault(a => a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL").Select(x => new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
});
To decouple yourself from the Entity Framework you may want to also consider using a different model class to return instead of the Entity Framework model.
What I ended up doing was:
foreach (BillPaymentSummary payment in billPayments)
{
var data = db.BillHistories.Where(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "B").FirstOrDefault();
if (data != null) // There is a bill history
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
else // No bill history record, look for an adjustment
{
data = db.BillHistories.FirstOrDefault(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "A");
if (data != null)
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
}
db.SaveChanges();
}
I currently have the following:
public IEnumerable<News> NewsItems
{
get { return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s; }
}
The problem is I only need to return the one property that actually has the data as well as the Title property, something similar to.
return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select new {Title = s.Title, Data = //Description or Summary containing the data
How do I determine which one contains the search query?
UPDATE: I have this but it obviously hits the DB 3 times
var FoundInSummary = News.All().Any(x => x.Summary.Contains(SearchCriteria));
var FoundInDesc = News.All().Any(x => x.Description.Contains(SearchCriteria));
IEnumerable<NewsEventSearchResults> result = null;
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
result = (from s in News.All() where s.Summary.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Summary, ID = s.ID }).AsEnumerable();
}
else if (FoundInDesc)
{
result = (from s in News.All() where s.Description.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Description, ID = s.ID }).AsEnumerable();
}
return result;
UPDATE 2: Is this more efficent?
var ss = (from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s).ToList();
List<NewsEventSearchResults> resultList = new List<NewsEventSearchResults>();
foreach (var item in ss)
{
bool FoundInSummary = item.Summary.Contains(SearchCriteria);
bool FoundInDesc = item.Description.Contains(SearchCriteria);
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Summary, ID = item.ID });
}
else if (FoundInDesc)
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Description, ID = item.ID });
}
}
What if they both contain the criteria? Or are they mutually exclusive? If so
Data = (s.Description != null ? s.Description : s.Summary)
I went with option 3