to get specific item from list obltained through LINQ - c#

I have following code,
var applications = from a in applications1.Entities.ToList()
select new
{
name = a.Attributes["sia_name"].ToString(),
applicationId = a.Attributes["sia_applicationid"].ToString(),
isDraftMode = a.Attributes.Contains("sia_applicationmode") ? a.FormattedValues["sia_applicationmode"].ToString().ToLower() == "draft" ? true : false : false
};
in this code I have applications which contains name ,applicationid,and isdraftmode,
now I want to fetch applicationid from var application so that I can pass it to session
how can it be achive
Session["ApplicationID"]=applications

do it like
Session["ApplicationID"]=applications.Select(m => m.applicationId).First();
it would give you first applicationId. If you want to select applicationId based on condition then you can do it like
Session["ApplicationID"]=applications.Select(m => m.applicationId).First(x => x.property == condition);
and for all the applicationid do it like
Session["ApplicationID"]=applications.Select(m => m.applicationId).ToList();

So you have a query which selects multiple properties in an anonymous type and you need to select one specific property from it to write it into session?
Session["ApplicationID"] = applications
.Select(x => x.applicationId)
.ToList(); // i would "materialize" it in a collection to avoid side effect due to lazy evaluation
or do you instead want to get a specific item from it, for example via sia_name?
var sia = applications.FirstOrDefault(x => x.sia_name == "InsertName");
if(sia != null)
Session["ApplicationID"] = sia.applicationId;

Related

Why cant we select any properties on the many side when we are using .Select(x=>new object) on Linq

i just wonder about something which has no sense to me. I'm using ASP.NET Core 5.0 and im using Linq.
I have a two class which has relationship One (MainCategory) - To - (Category) Many. I wanna write a linq which is gonna targeting to get MainCategoryName and CategoryID. Let me show to you my linq :
public IEnumerable<MainCategory> GetMainCategoryForFair()
{
return DBContext.MainCategories.Where(x => x.MainCategoryIsFeatured == true
&& x.IsDeleted != true)
.Select(x => new MainCategory
{
MainCategoryName = x.MainCategoryName,
Categories = x.Categories
}).ToList();
}
I know, that query gonna take all properties of Categories and this is the thing im trying to avoid. Is it possible ?
if it's possible,then how ?
if it's not, why ?
Sure. Just don't project all the properties. And normally if you are returning a different data shape, you would introduce a new class to return, instead of returning an Entity type with a bunch of null properties, eg
public IEnumerable<MainCategoryDTO> GetMainCategoryForFair()
{
return DBContext.MainCategories.Where(x => x.MainCategoryIsFeatured == true
&& x.IsDeleted != true)
.Select(x => new MainCategoryDTO()
{
MainCategoryName = x.MainCategoryName,
Categories = x.Categories.Select( c => new CategoryDTO(){CategoryName = c.Name, ...}).ToList()
}).ToList();
}

LINQ to Entities does not recognize the method Urls.MeaningfulURL, and this method cannot be translated into a store expression

This question is specific to taking in a formatted url value and comparing to an unformatted database value.
I have a url /companies/my-company/
The company's name is stored in the database field as "My Company" - note: no hyphen, space and uppercase.
It could be stored in an even more complex format like "John's Company >>" because the user has the ability to input this in the CMS.
So how do I compare my-company to My Company in LINQ to Entites?
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(x => new DataContracts.Content.Organisation
{
Id = x.Id
,Name = x.Name
,OrganisationTypeId = x.OrganisationTypeId
,OrganisationTypeName = (x.OrganisationType != null) ? x.OrganisationType.Name : string.Empty
,Categories = x.Categories.Select(i => i.Id)
,IsCustomer = x.IsCustomer
,CountryId = x.CountryId
,CountryName = (x.Country != null) ? x.Country.Name : string.Empty,
SeoName = x.SeoName,
Description = x.Description,
Website = x.Website
})
.FirstOrDefault(x => x.Id == id || Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower());
The problem here is:
Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower()
It generates an error:
LINQ to Entities does not recognize the method Urls.MeaningfulURL method, and this method cannot be translated into a store expression.
I understand what it means, but cannot figure out a way around it.
Urls.MeaningfulURL is a method that does a lot of string replacements to create the url format 'my-company'.
How can I format column x.SeoName at query time correctly so it matches my url input ?
Thanks
EF cann't translate Urls.MeaningfulURL to SQL. There are so many options to resolve it:
1. Load data first:
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(your select)
.ToList()
.FirstOrDefault(x => x.Id == id || Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower());
it's simplest but it produces perfomance problems cause all Organisation will be loaded from db into memory.
2. Rewrite your logic.
You cann't apply custom method to x.SeoName so just don't do that. Try to rewrite your query to:
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(your select)
.FirstOrDefault(x => x.Id == id || computedString.Contains(x.SeoName));
And yes, you can use Contains, at least for SQL Server provider.
3. Move your logic to SQL:
If SQL Server is used, you can try computed column, view, and even CLR code on SQL Server etc.
4. Store the computed value in db:
Sometimes it is better to store Urls.MeaningfulURL(x.SeoName.ToLower(), null) value instead or together with x.SeoName and use this stored value in queries. Also it becomes possible to add an index on this field.

LINQ Query comparing Id with an Id in a list inside SingleOrDefault query

I am trying to fetch an option using the SingleOrDefault Linq to SQL method.
var po = repository.Context.AsQueryable<Option>().SingleOrDefault(o => o.Option.Id == sp.Options // sp.Options is a collection);
The problem is that inside the SingleOrDefault method I am comparing p.Option.Id == a collection. What I want is to select the option from sp.Options that matches the o.Option.Id. How can I do that?
UPDATE:
One thing I should have mentioned that the sp.Options is a different class than the Option class. sp.Options is SPOptions class so I cannot pass it inside the contains method.
Take a look at Contains.
repository.Context.AsQueryable<Option>().SingleOrDefault(o => sp.Options.Contains(o.Option.Id));
If Options is not a collection of the class of Option.Id, you can use the Any method with your comparison logic in it as follow :
repository.Context.AsQueryable<Option>().SingleOrDefault(o => sp.Options.Any(opts => opts.Something == o.Option.Id));
Search using Contains (sp.Options.Contains(o.Option.Id)) like:
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Contains(o.Option.Id));
If members of sp.Options are different from Id then you can do:
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Any(r=> r.Id == o.Option.Id));
or
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Select(r=> r.Id).Contains(o.Option.Id));
Assuming Id is the field in sp.Options elements that you want to compare with.
Based on your question it seems you're expecting to have a single match between those two option sets, correct ?
If so, I'd suggest you to write it as:
var po = repository.Context.AsQueryable().Where(o => sp.Options.Any(item=>item.id == o.Option.Id)).SingleOrDefault();

asp.net MVC Where in List

I building my first application with c# and sp.net MVC 5, so far so good :)
Now I have a problem, we using 2 User Tables, first one contains the username, other the user data.
string user = User.Identity.Name;
var data = db.FE_Benutzer;
var collection = data.Where(o => o.Benutzername == user).Select(x => new
{
id = x.ID,
name = x.Name,
hauptbereiche = x.Hauptbereich.ToList()
});
var dataHauptbereich = db.Hauptbereich;
var collectionHauptbereich = dataHauptbereich.Where(o => collection.ElementAt(0).hauptbereiche.Contains(o)).Select(x => new
{
id = x.ID,
name = x.Name
});
return Json(collectionHauptbereich, JsonRequestBehavior.AllowGet);
I getting this error
LINQ to Entities does not recognize the method '<>f__AnonymousType63[System.Int32,System.String,System.Collections.Generic.List1[scorring.Models.Hauptbereich]] ElementAt[<>f__AnonymousType63](System.Linq.IQueryable1[<>f__AnonymousType63[System.Int32,System.String,System.Collections.Generic.List1[scorring.Models.Hauptbereich]]], Int32)' method, and this method cannot be translated into a store expression.
hauptbereiche = x.Hauptbereich.ToList()
contains a list of ids where the user have premission to.
When I fetching the data
dataHauptbereich.Where
I wont to include only the ids I have in the list
how is this possible?
Entity Framework doesn't know how to turn ElementAt into SQL. See this answer for more information: Getting the first result from a LINQ query - why does ElementAt<T>(0) fails when First<T>() succeeds?
Try
dataHauptbereich.Where(o => collection.ElementAt(0).hauptbereiche.Any(h => h.ID == o.ID))
Or
dataHauptbereich.Where(o => collection.Any(c => c.hauptbereiche.Any(h => h.ID == o.ID)))
I'm having a bit of a time deciphering exactly what you're trying to achieve with your code here, but it looks to me like your simply querying Hauptbereichs that belong to a particular user. Your first query selects an anonymous object composed of id, name and hauptbereiche, but of these you only ever use the hauptbereiche property. Then, in your second query, you merely selecting Hauptbereichs that match an item in this hauptbereiche property's collection. Actually, here, you're only comparing values from the first item in the original collection, which begs the question of why you're selecting anything other than the first item. That, and this second query is entirely redundant because if the items match that means you already had the items in the first place. You could get the same info directly from collection.ElementAt(0).hauptbereiche without issuing the second query.
So, here's a couple of simpler options:
If you're trying to get all the Hauptbereichs that belong to all the FE_Benutzers where Benutzername == user then just do:
var collectionHauptbereich = db.FE_Benutzer.Where(m => m.Benutzername == user)
.Include(m => m.Hauptbereich)
.SelectMany(m => m.Hauptbereich);
If you want just the first FE_Benutzer item's Hauptbereichs, then do:
var benutzer = db.FE_Benutzer.Where(m => m.Benutzername == user)
.Include(m => m.Hauptbereich)
.FirstOrDefault();
var collectionHauptbereich = benutzer != null
? benutzer.Hauptbereich.ToList()
: new List<Hauptbereich>();

LINQ sub list<> sometimes returns "NULL"

I have a LINQ query with a sublist in it which sometimes can return no returns, however can't manage to get the actual null instead of a error.
Any help in this would be appriciated.
var member_settings = from ml in _pMetaLanguages
join s in _settings
on ml.id equals s.setting_type_id
orderby ml.name descending
select new _class {
group_name = ml.name
, code = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().code
, name = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().name
, id = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().id
,
classUI = ml.metadataMUI
,
nameUI = ml.metadataMUI.Where(u => u.language_type_id.Equals(list_language_id))
.Select(i => new pMetaClasses
{
name = i.classes.Where(y => (y.bound_id.Equals(list_language_id))).FirstOrDefault().name
}).FirstOrDefault().name
, setting_type_id = s.setting_type_id
, int_value = s.int_value
};
EDITED
This part delivers the problems
nameUI = ml.metadataMUI.Where(u => u.language_type_id.Equals(list_language_id))
.Select(i => new pMetaClasses
{
name = i.classes.Where(y => (y.bound_id.Equals(list_language_id))).FirstOrDefault().name
}).FirstOrDefault().name
"metadataMUI" sometimes has records but not always, when no records it should be null (at least no error...
You have a collection of objects, it may or may not be empty. You want to pull out a property from the first item in that collection, if there is one. Currently whenever your query is face with this problem you are using this general approach:
sequence.FirstOrDefault().SomeMember
This code works fine if the sequence will always contain an item. It doesn't work if it may be empty. (Unless you can and want to get the member of the default value. For reference types, as you clearly are working with, this just results in null reference excpetions.) Fortunately there is a simple transformation to ensure that this works correctly. Simply use Select to transform the sequence into the sub-property that you are interested in and then get the first or default value of that sequence:
sequence.Select(item => item.SomeMember).FirstOrDefault();
This will work properly whether there are items or no items. The projection will never be called on default values using this approach.
Of course you do this in a lot of places, so you'll need to make this transformation throughout your query.

Categories

Resources