How To specify Where in Include in entity framework - entity-framework

I have faced this issue many times and I wanted to know the best approach to deal with Where clause in Include. Here is my sample code
IEnumerable<Data.StoreMenu> dataStoreMenus = _context.StoreMenus
.Include(sm => sm.MenuCategories.Where(x => !x.IsDeleted))
.Where(sm => sm.StoreId == storeId && !sm.IsDeleted).ToList();
The scenario is I have a menu and Menu has multiple menu categories. Both menu and menu categories has a flag to mark items deleted. Now I want to retrieve only non-deleted menu along with NON-DELETED menu categories.

Create a subquery:
var result = _context.StoreMenus
.Where(sm => sm.StoreID == storeId && !sm.IsDeleted)
.Select(sm=>
new { Menu=sm, MenuCats = sm.MenuCategories.Where(smc => !smc.IsDeleted) })
.ToList();
Might want to have a look at something similar: here

Related

use Intersect into IQueryable and EfCore

I'm trying to use LinQ Intersect (or equivalent) into an IQueryable method but it seems like I'm doing it wrong.
I have some PRODUCTS that match some SPECIFITY (like colors, materials, height...), those specifications have different values, for example:
color : blue, red, yellow
height : 128cm, 152cm...
I need to get the products that match ALL the list of couple specifityId / specifityValue I provide.
Here what I'm trying to do:
// The list of couple SpecifityID (color, material..) / SpecifityValue (red, yellow, wood...)
List<string> SpecId_SpecValue = new List<string>();
SpecId_SpecValue.Add("3535a444-1139-4a1e-989f-795eb9be43be_BEA");
SpecId_SpecValue.Add("35ad6162-a885-4a6a-8044-78b68f6b2c4b_Purple");
int filterCOunt = SpecId_SpecValue.Count;
var query =
Products
.Include(pd => pd.ProductsSpecifity)
.Where(z => SpecId_SpecValue
.Intersect(z.ProductsSpecifity.Select(x => (x.SpecifityID.ToString() + "_" + x.SpecifityValue)).ToList()).Count() == filterCOunt);
I got the error : InvalidOperationException: The LINQ expression 'DbSet() could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information. which mean it can't be translated to SQL and I need to ToList before my filter.
The problem is, I don't want to call ToList() because I got huge number of products in my Database and I don't want to load them in memory before filtering them.
Is there an other way to achieve what I need to do?
I ended up using a solution found in the link #Gert Arnold provide here.
I used BlazarTech.QueryableValues.SqlServer #yv989c's answers
Here's what is now working like a charm :
// The list of couple SpecifityID (color, material..) / SpecifityValue (red, yellow, wood...)
Dictionary<Guid, string> SpecId_SpecValue = new Dictionary<Guid, string>();
SpecId_SpecValue.Add(new Guid("3535a444-1139-4a1e-989f-795eb9be43be"), "BEA");
SpecId_SpecValue.Add(new Guid("35ad6162-a885-4a6a-8044-78b68f6b2c4b"), "Purple");
// BlazarTech.QueryableValues.SqlServer
var queryableValues = DbContext.AsQueryableValues(SpecId_SpecValue);
var query = Products.Include(pd => pd.ProductsSpecifity)
.Where(x => x.ProductsSpecifity
.Where(e => queryableValues
.Where(v =>
v.Key == e.SpecifityID &&
v.Value == e.SpecifityValue
)
.Any()
).Count() == dynamicFilter.Count);
The query expresses "products of which all x.SpecifityID.ToString() + "_" + x.SpecifityValue combinations exactly match some given combinations".
Set combination operators like Except often don't play nice with EF for various reasons I'm not going into here. Fortunately, in many of these cases a work-around can be found by using Contains, which EF does support well. In your case:
var query = Products.Include(pd => pd.ProductsSpecifity)
.Where(z => z.ProductsSpecifity
.Select(x => x.SpecifityID.ToString() + "_" + x.SpecifityValue)
.Count(s => SpecId_SpecValue.Contains(s)) == filterCount);
Please note that the comparison is not efficient. Transforming database values before comparison disables any use of indexes (is not sargable). But doing this more efficiently isn't trivial in EF, see this.

webapi entity frameworks - best way to return nested classes where

Based on this diagram using webapi entity frameworks, what would be the best way to say, return me all Menus.text.... where AspNetUsers.Username = xxxx.
I think I need to start with a MenusController, and say return Menus(Include Permissions, include groups, include AspNetUsers, where username = x.
Is that the best way?
If you only need text field of menu, not use include, better is use projection to load desired fields as following:
var menuTextList = db.Users.Where(e=> e.Username = "xxxx")
.Select(e=> e.Group)
.SelectMany(e=> e.Permissions)
.Select(e=> e.Menu)
.Select(e=> e.text)
.Distinct()
.ToList();
and for all fields in menus, as following:
var munuList = db.Users.Where(e=> e.Username = "xxxx")
.Select(e=> e.Group)
.SelectMany(e=> e.Permissions)
.Select(e=> e.Menu)
.Distinct()
.ToList();

I want to get the master items rather from my dynamic module

FooFooManager.Speakers.GetAll() gets the live items however I want the master items
This doesn't work FooFooManager.Speakers.GetAll().Where(s => s.Status == ContentLifecycleStatus.Master);
How can I get the master items?
Thanks,
Yes, you can pass in a filter before it reaches Babaganoush, like this:
BabaManagers.News.GetAll(
filter: x => x.Status == ContentLifecycleStatus.Master
);
More details can be found here: http://babaganoush.falafel.com/documentation/tutorials/how-to-retrieve-data

how to validate dropdown optionlist required functionality asp.net mvc

I have dropdown like this ,
<%= Html.OptionList("Worktype", new SelectList(new List<SelectListItem>{
new SelectListItem{Text = "--Select One--", Value = "0", Selected=true},
new SelectListItem{Text = "Fulltime", Value = "Full Time"},
new SelectListItem{Text = "Partime", Value = "Part Time"}}, "Value", "Text" )) %>
After selecting either fulltime or parttime it should submit, but because the default select is there, required validation is passing. I want the required validation for below two options. can anyone help me out.
thank you,
michael
SetValue empty instead of 0 for "--Select One--"
new SelectListItem{Text = "--Select One--", Value = string.Empty , Selected=true}
I suggest that you should not be adding optional label in SelectList or as SelectListItem. you have overloads for Html.DropDown and Html.DropDownListFor that would allow you to insert an optional label at the top of your dropdown list. Pleas check my answer to this question.
DO you want to fire any event only in case of full time and part time and in case of select you dont want anything to happen.
If this is what you want
$('#dropdownname').change(function () {
var dropdownValue = $(this).val();
if (dropdownValuetoString().length > 0)
{
Your Code here.........
}
});
dropdownname is the name of dropdown dropdownValue is what I m getting from dropdown list when index is changed.
I was filling the dropdown from a list and I was not using any value field
when u check the dropdownValue for select It will show blank and I m sure ur dropdown select list will always have a name.
Tell me if it helps you else I will try something different

MVC 3 - Entity Framework & POCO - Many to Many REMOVAL on ActionLink()

I have Many to Many Relationships for:
Company -----> CompanyVenue <------
Venue
I can currently add a Venues to a Companies and Companies to Venues.
The Add Venue link takes the user to this view: (using this controller logic):
var venue = context.Companies.Select(x => x.Venues.Where(xy => xy.VenueId == id));
var company = venue.Select(x => x.);
ViewData["CompanyFor"] = company;
ViewData["VenueFor"] = venue;
Once the User Selects the Venue and Clicks the ADD VENUE Button, it passes the ViewModel back to Controller:
Company c = context.Companies.Single(x => x.CompanyId == model.CompanyId);
Venue v = context.Venues.Single(x => x.VenueId == model.VenueId);
c.Venues.Add(v);
context.SaveChanges();
So That is how I implimented the Many-Many Add. But, I Am looking for some help with Removal Controller Code / View (If Needed) / Possibly A View Model (but don't really see the need for what is essential a simple action)
In the Company Details View I am trying to get REMOVE Link underneath each Venue Item to Remove the [CompanyVenue] (many2many) Relationship.
If it is possible to pass 2 Values instead of one using this type of ActionLink():
#Html.ActionLink("Remove", "VenueRemove", new { Id = venue.VenueId }, new { Cid = model.CompanyId } )
it would be easy, but I have not figured out a way (load method) to pass both Values ( Id & Cid ) back to a VenueRemove() Controller Action, that would then return a RedirectToAction() back to the Company Details view.
If someone knows how to do that Please let me know. (Thank You Darin for the awnser to that)
I went ahead and got the Remove Working Using a View.
But is there anyway to get the Remove to work by just clicking the REMOVE Link/button and have it remove the venue with out going to the view?
Maybe an AJAX request or something.... ???
You can pass two parameters to the VenueRemove action like this:
#Html.ActionLink(
"Remove",
"VenueRemove",
new {
Id = venue.VenueId,
Cid = model.CompanyId
}
)