How do I detect field changes in EF? - entity-framework

In EF4, I want to know if some fields has been changed. How can I do that?

var propertyFooIsModified =
Context.ObjectStateManager.GetObjectStateEntry(someEntity)
.GetModifiedProperties.Any(p => p == "Foo");

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.

How To specify Where in Include in 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

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();

Dijit/Dojo Inline - Filtering Select - DataStore

I am using an inline filteringselect with datastore, as follows:
I am using ABBR as the identifier and NAME as the value.
The filtering selects and works correctly, but I have two issues.
Firstly, how do I retrieve the ABBR for the selected option NAME?
I have tried various things, including .innerHTML but that only retrieves the selected item name, not the identifier.
Secondly, when using the datastore option, how can I choose the default selected item, for example if it was a scale of 1 to 10 and I wanted 5 as the default selection, how can I do this?
Any ideas and advice would be greatly appreciated.
Mank thanks
dojo.addOnLoad(function() {
// inline store
str = new dojo.data.ItemFileReadStore({data: storeData10})
var itmes;
// for storing the store's items
str.fetch({
onComplete:function(itms){
itmes= itms;
console.log(itms)
}
})
dijit.byId("cmbx1").store = str
dojo.connect(dijit.byId("cmbx1"), 'onChange',function(){
//console.log(arguments);
//get the value u c in screen
var whatvseeinselect = dijit.byId("cmbx1").focusNode.value;
dojo.forEach(itmes, function(itm){
//compare the value u c in screen with store itms. once matched take that item and get the name attr or other attr if u require..
if(whatvseeinselect == str.getValue(itm,"name")){
console.log(str.getValue(itm,"name"));
}
})
})
});
I'm not sure whether this is the correct way.
Hope this helps

How do I disable some entities based on a few properties in NHibernate Search?

Im still pretty new to NHibernate.Search so please bear with me if this is stupid question :)
Say, I have indexed some entities of type BlogPost, which has a property called IsDeleted. If IsDeleted is set to true, I don't want my queries to show this particular blogpost.
Is this possible? And if it is - How? :P
Thanks in advance
- cwap
// Using NHibernate.Linq:
var result = Session.Linq<BlogPost>().Where(post => !post.IsDeleted).ToList();
// Using HQL:
var hql = "from BlogPost bp where bp.IsDeleted == false";
var result = Session.CreateQuery(hql).List<BlogPost>();
// Using Criteria API:
var result = s.CreateCriteria(typeof(BlogPost))
.Add(Restrictions.Eq("IsDeleted", false));
.List<BlogPost>();
NHibernate.Linq
HQL: Hibernate Query Language
Found the solution myself. I added the [Field(Index.Tokenized, Store = Store.Yes)]-attribute to the IsDeleted property, and added this clause to any query inbound:
string q = "(" + userQuery + ") AND IsDeleted:False";
I knew it was something simple :)