Limit the rows returned in Include entity - entity-framework

I have simple data model Project,Member and ProjectMember where Project to Member has many-to-many relationship. Therefore ProjectMember table contains the both foreign keys.
I writes the code
var result= db.Projects.Include(p=>p.ProjectMembers).Where(p=>p.ProjectMembers.Any(pm=>pm.DeletedUser==1));
and I see result.ProjectMembers count is 2 . Here I have got additional record with DeletedUser is not equal to 1
Did I do something wrong here?
What is the expression I have to use to get the only one record (or many with DeletedUser=1) for result.ProjectMembers

You are asking for Projects having at least one (= any) ProjectMember with DeletedUser == 1. This condition is met. Other ProjectMembers of the Project can have any other value than 1 for DeletedUser.
If you want the Project with only ProjectMembers with DeletedUser == 1 you should start the query at ProjectMember:
ProjectMembers.Include("Project").Where(pm => pm.DeletedUser == 1)

Related

Error "Store update, insert, or delete statement affected an unexpected number of rows (0)" Entity Framework

I'm trying to process a datatable table queue without duplicates.
My table has 3 fields: A (ID), B (ID) and C (DateTime).
A and B are PK.
Every 10 minutes, I process the queue. First, I call to
DB.Items.AsNoTracking().OrderBy(x => x.C).Select(x => new Item { A = x.A, B = x.B }).Distinct().ToList();
This way, if there are 2 duplicate items in the queue, only one should be selected. However, I don't know why but sometimes 2 duplicate items are added to the result of that call.
Then, I do a foreach and process the items one by one. Each time, I process an item, I call this:
Item itemDB = DB.Items.OrderBy(x => x.C).FirstOrDefault(x => x.A == Aparam && x.B == Bparam);
if (itemDB != null)
DB.Items.Remove(itemDB);
return DB.SaveChanges();
I don't know why but sometimes I get this exception:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
On the other hand, I don't know why duplicate items are returned in the first call if I'm calling the Distinct method.
I think both issues are related but I don't find a solution.
If someone could help me, I would thank you!
Ariel

Entity Framework Relationship Definition Issue

In my application I have Sections, Tables, Rounds and Players.
Each Section has N Tables (Table "Keys": SectionId, TableId).
And each Table has N Rounds (Round "Keys": SectionId, TableId, RoundNumber)
Players start at a Table but move to other Tables each Round, and are identified by the Table they started at.
In a perfect universe, I'd be able to put a Collection of Players on the Round object, and query for the right ones inside my controller. I get the round and then I'd do something like this:
db.Entry(theRound)
.Collection(p => p.Players)
.Query()
.Where(p=> (p.SectionId == theRound.SectionId) &&
((p.TableNumber == theRound.NSPair && (p.Direction == "N" || p.Direction == "S")) ||
(p.TableNumber == theRound.EWPair && (p.Direction == "E" || p.Direction == "W"))))
.Load();
Problem is, once I declare the Collection of Player Objects in Round, Entity Framework puts "Round_XXXX" fields for each of the three Round keys above into the table for Players, including it in the where clauses of that query. And it won't find them because they aren't associated with Rounds...not in that sense, anyway.
Associating a Round object with the Table Objects that the Players start at (in addition to it's "normal one) seems to be an awful kludge.
What I've done for now is annotated the Players collection to be [NotMapped] and executed the query from the root level context.
There is a better way to do this, right?

sqlalchemy updating all records ignoring filter

Have been bug hunting all day and located the following unexpected behaviour with sqlaclhemy (flash-sqlalchemy to be precise).
The code is
actionId = 1
DataLists.query.\
join(Actions, actions.action_id == DataLists.action_id).\
filter(Actions.action_id == actionId).\
update({DataLists.dt_cancelled: datetime.utcnow()})
#Updates ALL DataLists!
The query (without the update) returns 1 record, yet ALL records are updated.
#testing
rows = DataLists.query.\
join(Actions, actions.action_id == DataLists.action_id).\
filter(DataLists.action_id == actionId).\
all()
print("rows: {}".format(len(rows))) # outputs 1
From what I understand, the update works on the returned rows. Which is not happening, so I must be missing something here.
I have tried to get a copy of the SQL statments, but the update statement doesn't appear to work like a normal query, so
sql = DataLists.query.\
join(Actions, actions.action_id == DataLists.action_id).\
filter(Actions.action_id == actionId).\
update({DataLists.dt_cancelled: datetime.utcnow()})
print(str(sql))
doesn't work, and returns that 114 rows were updated
Now it turns out that the join isn't infact needed and the query can be written as
DataLists.query.\
filter(DataLists.action_id == actionId).\
update({DataLists.dt_cancelled: datetime.utcnow()})
#testing
rows = DataLists.query.\
filter(DataLists.action_id == actionId).\
all()
print("rows: {}".format(len(rows))) # outputs 1
strangely (to me anyway) this now works as expected. Just a single row is updated.
So the issue is with the join. But each DataList is joined on a foreign key 'action_id', this is unique and does not ever return multiple rows.
So does the update command not work with a join? Or is there a glaring bug in the above code I am blind to?

EntityFramework counting of query results vs counting list

Should efQuery.ToList().Count and efQuery.Count() produce the same value?
How is it possible that efQuery.ToList().Count and efQuery.Count() don't produce the same value?
//GetQuery() returns a default IDbSet which is used in EntityFramework
using (var ds = _provider.DataSource())
{
//return GetQuery(ds, filters).Count(); //returns 0???
return GetQuery(ds, filters).ToList().Count; //returns 605 which is correct based on filters
}
Just ran into this myself. In my case the issue is that the query has a .Select() clause that causes further relationships to be established which end up filtering the query further as the relationship inner join's constrain the result.
It appears that .Count() doesn't process the .Select() part of the query.
So I have:
// projection created
var ordersData = orders.Select( ord => new OrderData() {
OrderId = ord.OrderId,
... more simple 1 - 1 order maps
// Related values that cause relations in SQL
TotalItemsCost = ord.OrderLines.Sum(lin => lin.Qty*lin.Price),
CustomerName = ord.Customer.Name,
};
var count = ordersData.Count(); // 207
var count = ordersData.ToList().Count // 192
When I compare the SQL statements I find that Count() does a very simple SUM on the Orders table which returns all orders, while the second query is a monster of 100+ lines of SQL that has 10 inner joins that are triggered by the .Select() clause (there are a few more related values/aggregations retrieved than shown here).
Basically this seems to indicate that .Count() doesn't take the .Select() clause into account when it does its count, so those same relationships that cause further constraining of the result set are not fired for .Count().
I've been able to make this work by explicitly adding expressions to the .Count() method that pull in some of those aggregated result values which effectively force them into the .Count() query as well:
var count = ordersData.Count( o=> o.TotalItemsCost != -999 &&
o.Customer.Name != "!##"); // 207
The key is to make sure that any of the fields that are calculated or pull in related data and cause a relationship to fire, are included in the expression which forces Count() to include the required relationships in its query.
I realize this is a total hack and I'm hoping there's a better way, but for the moment this has allowed us at least to get the right value without pulling massive data down with .ToList() first.
Assuming here that efQuery is IQueryable:
ToList() actually executes a query. If changes to data in the datastore, between calls to ToList() and .Count(), result in a different resultset, calling ToList() will repopulate the list. ToList().Count and .Count() should then match until the data in the store changes the resultset again.

How to write query in Entity Framework

I'm new to Entity Framework. I have a database query which I need to convert to Entity Framework. how to write the query in LinQ to Enity
Can someone help me on that?
SELECT
FLD1,
FLD2,
SUM(FLD3),
(TO_CHAR(FLD4,'MM/DD/YYYY'))
FROM
TABLE1
WHERE
(FLD2=XXX ) AND
(FLD3 BETWEEN TO_DATE(VARDATE,'MMDDYYYY') AND TO_DATE(VARDATE1,'MMDDYYYY'))
GROUP BY
FLD1,
FLD2,
FLD4
Well...info is sparse and you filled it with a lot of different cases something like this would do.
_context.SomeObject
.Where(x=>x.SomeField == "SomeValue" && x.SomeField > 5 && x.SomeField < 10)
.Select(x=>new { x.SomeField1, x.SomeField2, x.SomeField2, SomeField4 = x.SomeChildCollection.Sum(y=>y.SomeChildvalue)
.GroupBy(x=>new {x.SomeField1, x.SomeField2, x.SomeField3})
.ToList()
This would result in a group where the key was an object with the values SomeField1, SomeField2, SomeField3, and the object would be the an anonymous projection with the 4 properties in the Select.
In some kinds of comparisions regarding dates you might need to use EntityFunctions.