Below is my code
var dbClaimLink = this.Context.Set<ClaimLink>();
var claims = await DbSet
.Include(claim => claim.Parent)
.Include(link => link.ParentLinks)
.ToListAsync();
var newClaimLink = await dbClaimLink.ToListAsync();
var processedClaims = claims.Select(x =>
{
var claimLinks = x.ParentLinks;
if (!claimLinks.Any())
{
return x;
}
var hiddenParents = claimLinks.Select(p => claims.Find(t => t.Id == p.ClaimLinkId));
x.HiddenParents = hiddenParents;
return x;
});
foreach (var objClaim in processedClaims)
{
if (objClaim.Children == null)
objClaim.Children = new List<Claim>();
var lst = newClaimLink.Where(k=> k.ClaimLinkId == objClaim.Id).ToList();
if (lst.Any())
{
foreach (var item in lst)
{
IEnumerable<Claim> newChildren = claims.Where(p => p.Id == item.ClaimId);
objClaim.Children.Concat(newChildren);
}
}
}
it always return old children set without concatenate with new children. I want to those old and new children set concatenate in side of foreach loop
the Concat method returns a new collection with both values and does not alter the original.
Concat will return new object - result of concatination, so you need to save it somewhere: var result = objClaim.Children.Concat(newChildren);
Where is lazy operation, it does not execute in place, only after materialization (ToArray, or foreach call): claims.Where(p => p.Id == item.ClaimId).ToArray()
Related
Is it possible to select two rows into one anonymous object DTO with two properties?
With a model like:
public class Document
{
public int Id { get; set; }
public string Text { get; set; }
// Other properties
}
I am writing a method that finds the difference between two versions of a document:
public Task<string> CompareVersions(int initialId, int finalId)
So I need to retrieve the text of exactly two Documents by Id, and I need know which was which.
Currently I am constructing a Dictionary<int, string> by doing:
var dto = await _context.Documents
.Where(doc => doc.Id == initialId
|| doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
and then calling dto[initialId] to get the text. However, this feels very cumbersome. Is there any way to take the two Ids and select them into one DTO in the form
{
InitialText,
FinalText
}
You have to use SelectMany
var query =
from initial in _context.Documents
where initial.Id = initialId
from final in _context.Documents
where final.Id = finalId
select new
{
InitialText = initial.Text,
FinalText = final.Text
};
var result = await query.FirstOrDefaultAsync();
Aggregate can do it too
var dto = (await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId).ToListAsync())
.Aggregate(
new { InitialText = "", FinalText = "" },
(seed, doc) => {
if(doc.Id == initialId)
seed.InitialText = doc.Text;
else
seed.FinalText = doc.Text;
}
);
I'm not sure I like it any more than I do your dictionary approach, but with an actual dto at the end rather than the dictionary:
var d = await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
var dto = new { InitialText = d[initialId], FinalText = d[finalId] };
You could also perhaps just:
var dto = new {
InitialText = await context.Documents
.FindAsync(initialId),
FinalText = await context.Documents
.FindAsync(finalId)
};
Given a return of type "AccountItem", I want to filter and sort to a new list of type FDKeyValue<>
I am trying to do this without looping and I thought I could do something like this:
var monthlyList = accountList.Where(x => x.RoleType == "Metric")
.OrderBy(x => x.EntityName)
.Select(new FDKeyValue<long, string>{}
{
"Field", "Field"
}
);
here is what I have working with a loop
var accountList = DBEntity.ReturnAccountListBySearch((int)this.PageLanguageType, "");
var monthlyList = accountList.Where(x => x.RoleType == "Metric").OrderBy(x => x.EntityName).ToList();
this.MonthlyAccountList = new FDKeyValue<long,string>();
foreach (var item in monthlyList)
{
this.MonthlyAccountList.Add(item.EntityID, item.EntityName);
}
This syntax must help
var monthlyList = accountList.Where(x => x.RoleType == "Metric")
.OrderBy(x => x.EntityName)
.Select(x => new FDKeyValue<long, string>
{
x.EntityID, x.EntityName
}
);
I have a function returning a report object, but currently i am going through a foreach look and then using the asQueryable method.
I would like to do it in one query and not have to use the AsQueryable function.
var query = from item in context.Dealers
where item.ManufacturerId == manufacturerId
select item;
IList<DealerReport> list = new List<DealerReport>();
foreach (var deal in query)
{
foreach (var bodyshop in deal.Bodyshops1.Where(x => x.Manufacturer2Bodyshop.Select(s => s.ManufacturerId).Contains(manufacturerId)))
{
DealerReport report = new DealerReport();
report.Dealer = deal.Name;
report.Bodyshop = bodyshop.Name;
short stat = bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId).ComplianceStatus;
report.StatusShort = stat;
list.Add(report);
}
}
return list.OrderBy(x => x.Dealer).AsQueryable();
I think you want something like this:
var query = from deal in context.Dealers
where deal.ManufacturerId == manufacturerId
from bodyshop in deal.Bodyshops1
where bodyshop.Manufacturer2Bodyshop.Select(s => s.ManufacturerId).Contains(manufacturerId)
let stat = bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId)
orderby deal.Name
select new DealerReport
{
Dealer = deal.Name,
Bodyshop = bodyshop.Name,
StatusShort = stat != null ? stat.ComplianceStatus : 0, // or some other default
};
return query;
I am able to filter the data with the following two parameters id1 and id2, and get accurate result of 10 records, from which have 9 with a price_type=cs and other with price-type=ms.
However, if I add price_type to the parameters id1 and id2 (id1=23456,567890&id2=6782345&price_type=ms), I get 3000 records instead of getting one record.
Am I missing something in the code. Any help would be very much appreciated.
var data = db.database_BWICs.AsQueryable();
var filteredData = new List<IQueryable<database_Data>>();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.Name != null && c.Name.Contains(i)));
}
}
if (!string.IsNullOrEmpty(query.id2))
{
var ids = query.id2.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.ID2!= null && c.ID2.Contains(i)));
}
}
if (!string.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.ID1!= null && c.ID1.Contains(i)));
}
}
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.Type.Contains(i)));
}
}
if (filteredData.Count != 0)
{
data = filteredData.Aggregate(Queryable.Union);
}
Updated Code:
var data = db.database_BWICs.AsQueryable();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
data = data.Where(c => c.Name != null && ids.Contains(c.Name));
}
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
data = data.Where(c => ids.Contains(c.Cover));
}
if (!String.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
data = data.Where(c => c.ID1!= null && ids.Contains(c.ID1));
}
Because you don't add filter to restrict, every filter adds datas to result.
It means you make OR between your filters, not AND.
And your usage of contains looks rather strange too : you're using String.Contains, while I would guess (maybe wrong) that you want to see if a value is in a list => Enumerable.Contains
You should rather go for something like this (withoud filteredData)
var data = db.database_BWICs.AsQueryable();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
data = data.Where(c => c.Name != null && ids.Contains(c.Name)));
}
//etc.
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
data = data.Where(c => ids.Contains(c.Type));
}
EDIT
Well, if you wanna mix and or conditions, you could go for PredicateBuilder
Then your code should look like that (to be tested).
//manage the queries with OR clause first
var innerOr = Predicate.True<database_BWICs>();//or the real type of your entity
if (!String.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
innerOr = innerOr.Or(c => c.ID1!= null && ids.Contains(c.ID1));
}
if (!String.IsNullOrEmpty(query.id2))
{
var ids = query.id2.Split(',');
innerOr = innerOr.Or(c => c.ID2!= null && ids.Contains(c.ID2));
}
//now manage the queries with AND clauses
var innerAnd = Predicate.True<database_BWICs>();//or the real type of your entity
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
innerAnd = innerAnd.And(c => ids.Contains(c.Type));
}
//etc.
innerAnd = innerAnd.And(innerOr);
var data = db.database_BWICs.AsQueryable().Where(innerAnd);
The following method is causing the FIRST db.SaveChanges() to throw an exception:
(New transaction is not allowed because there are other threads running in the session.)
protected void btnInsertDependencies_Click(object sender, EventArgs e)
{
using (icmsEntities db = new icmsEntities())
{
var divisions = db.Divisions;
foreach (var division in divisions)
{
var dlc_sectors = db.Sectors.Where(s => s.Website.division_id == division.division_id).DistinctBy(s => s.name).ToList();
foreach (var sector in dlc_sectors)
{
dlc_Sector dlc_sector = new dlc_Sector
{
name = sector.name,
division_id = sector.Website.division_id
};
db.dlc_Sectors.AddObject(dlc_sector);
var dlc_products = db.Products.Where(p => p.Sectors
.Any(s => s.Website.division_id == dlc_sector.division_id && s.name == dlc_sector.name))
.DistinctBy(p => p.name).ToList();
foreach (var product in dlc_products.ToList())
{
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name);
if (dlc_product == null)
{
dlc_product = new dlc_Product { name = product.name };
db.dlc_Products.AddObject(dlc_product);
}
dlc_product.dlc_Sectors.Add(dlc_sector);
db.SaveChanges();
}
}
}
db.SaveChanges();
}
}
The first db.SaveChanges() is to make sure that a new product having the same name does not get inserted again.
How can I resolve this? Thanks in advance.
Worked for me:
var Local = db.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added)
.Where(es => es.Entity is dlc_Product).Select(es => es.Entity as dlc_Product);
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name)
?? Local.SingleOrDefault(p => p.name == product.name);
Thanks.
Not sure why this occurs, but the first SaveChanges() would not be necessary if you also checked the Local collection of db.dlc_Products:
foreach (var product in dlc_products.ToList())
{
var dlc_product = db.dlc_Products.SingleOrDefault(p => p.name == product.name)
?? db.dlc_Products.Local.SingleOrDefault(p => p.name == product.name);
...
}
New objects are added to the Local collection.
Note that db.dlc_Products.Join(db.dlc_Products.Local) looks more efficient, but it does not compile, and the other way around it queries the whole db.dlc_Products for each call.