I'm using Slick with Play but am having some problems when trying to update a column value as it is not being updated, although I don't get any error back.
I have a column that tells me if the given row is selected or not. What I want to do is to get the current selected value (which is stored in a DB column) and then update that same column to have the opposite value. Currently (after many unsuccessful attempts) I have the following code which compiles and runs but nothing happens behind the scenes:
val action = listItems.filter(_.uid === uid).map(_.isSelected).result.map { selected =>
val isSelected = selected.head
println(s"selected before -> $isSelected")
val q = for {li <- listItems if li.uid === uid} yield li.isSelected
q.update(!isSelected)
}
db.run(action)
What am I doing wrong (I am new to slick so this may not make any sense at all!)
this needs to be seperate actions: one read followed by an update. Slick allows composition of actions in a neat way:
val targetRows = listItems.filter(_.uid === uid).map(_.isSelected)
val actions = for {
booleanOption <- targetRows.result.headOption
updateActionOption = booleanOption.map(b => targetRows.update(!b))
affected <- updateActionOption.getOrElse(DBIO.successful(0))
} yield affected
db.run(actions)
Update:
Just as a side note, RDBMSs usually facilitate constructs for performing updates in one database roundtrip such as updating a boolean column to it's opposite value without needing to read it first and manually negate it. This would look like this in mysql forexample:
UPDATE `table` SET `my_bool` = NOT my_bool
but to my knowledge the high level slick api doesn't support this construct. hence the need for two seperate database actions in your case. I myself would appreciate it if somebody proved me wrong.
Related
At one point using FromSqlRaw to call stored procedures worked for me. I did not change anything in the project but now calling any stored procedure using FromSqlRaw returns
The underlying reader doesn't have as many fields as expected
I removed the model from the project and performed a BUILD. Then added the model back with no luck. I reduced the model and stored procedure to return a single column, no luck.
I tried adding Microsoft.EntityFrameworkCore.Relational as a dependency, no luck. All my unit test that use FromSqlRaw to call a stored procedure return the same error and at one time they all worked.
I have received Windows updates but nothing I know about that would have affected EF Core. I have run through all internet problem solving I can find. I am starting to think I will need to use ADO as a work around but I do not want a work around when it worked for me at one point. Something changed on my machine but I am not sure what to cause this problem.
Here is my test method in case my code is messed up. It is very straight forward not much to mess up. I tried the "var" out of desperation.
[TestMethod]
public void WorkOrderBOMGridABS()
{
List<WorkOrderBOMGridABS> baseList = new List<WorkOrderBOMGridABS>();
using (WorkOrderDataContext context = new WorkOrderDataContext())
{
var param = new SqlParameter[] {
new SqlParameter() {
ParameterName = "#WorkOrderId",
SqlDbType = System.Data.SqlDbType.Int,
Direction = System.Data.ParameterDirection.Input,
Value = 38385
}
};
baseList = context.WorkOrderBOMGridABS.FromSqlRaw("[dbo].[WorkOrderBOMGridABS] #WorkOrderId", param).ToList();
//var results = context.WorkOrderBOMGridABS.FromSqlRaw("[dbo].[WorkOrderBOMGridABS] #WorkOrderId", param).ToList();
Assert.IsNotNull(baseList);
}
}
I was using an old table to get the Unit Of Measure value that had an integer ID value. I switched it to use a new table with a VARCHAR ID value. Making this change to the stored proc and model code allowed the FromRawSql to work. Not sure why because while the integer ID value was getting an integer, either 0 or number other than 0, it was a valid value for the model. Any error message I received did not mention this UnitId field. It was a pain but I am glad it is resolved. At least until the next error I run into that much is guaranteed.
I'm trying to test the length of a react table.
In particular I would want that after a user add a new row to the table it's length would increase by one
In my code I can't extract the length value of the table and save it in the variable rowsLength so that it can be checked later, what am I doing wrong?
It seems rowsLength is an object not a number..
const rowsLength = cy.get(".MuiTableBody-root").find("tr").its("length");
cy.get("#addRowButton").click();//new tr inserted
cy.get(".MuiTableBody-root").find("tr").should("have.length", rowsLength + 1);
Setting a global variable quite often will not work, because of the asynchronous nature of a web app. The docs refer to this as doing a backflip.
The most reliable way to handle this is either with a closure or with an alias.
Closures
To access what each Cypress command yields you use .then().
cy.get(".MuiTableBody-root").find("tr").its('length').then(intialLength => {
// Code that uses initialLength is nested inside `.then()`
cy.get("#addRowButton").click();
cy.get(".MuiTableBody-root").find("tr").should("have.length", intialLength + 1);
})
Aliases
Allows you to separate the code that creates the variable from the code that uses it.
cy.get(".MuiTableBody-root").find("tr").its('length').as('intialLength');
cy.get("#addRowButton").click();
// other test code
cy.get('#intialLength').then(intialLength => {
cy.get(".MuiTableBody-root").find("tr").should("have.length", intialLength + 1);
})
Why not a global variable?
Using a global variable is anti-pattern because it often creates a race condition between the test code and the queued commands.
By luck, your example will work most times because cy.get("#addRowButton").click() is a slow operation.
But if you want to test that the row count has not changed, then using a global variable will fail.
Try this
var intialLength = 0;
cy.get('table').find("tr").then((tr) => {
intialLength = tr.length;
})
// Test that row count remains the same
cy.get('table').find("tr").should("have.length", intialLength);
// fails because it runs before the variable is set
This is because the test code runs much faster than the .get() and .find() commands, which must access the DOM.
Although the above example is trivial, remember that web apps are inherently asynchronous and backflip tests can easily fail.
With find() you can do something like:
var tableLen = 0;
cy.get(".MuiTableBody-root").find("tr").then((tr) => {
tableLen = tr.length,
})
and then:
cy.get("#addRowButton").click(); //new tr inserted
cy.get(".MuiTableBody-root").find("tr").should("have.length", tableLen + 1);
Given a Parent and a valid columnName, I want to find all the related Children, ordered by a dynamic column name. Here's how I thought my code would look:
Parent. // EntityObject
Children. // EntityCollection
Where(c => c.Gender == 'm'). // IEnumerable
OrderBy(columnName, ListSortDirection.Ascending). // -- not available --
Skip(pages * pageSize).Take(pageSize);
IEnumerable.OrderBy(string columnName) doesn't exist. Looking around to accomplish the "sort by dynamic column name", I started with this excellent-looking solution: How do I create an expression tree for run time sorting? , but this operates on an IQueryable
If it did, I assume it would bring the records over the wire to sort and diminish the performance of my pager anyway. So I reordered:
Repository. // Repository
Children. // ObjectSet
Where(c => c.Parent == Parent && c.Gender == 'm'). // ObjectQuery, runtime error
OrderBy(columnName, ListSortDirection.Ascending). // IOrderedQueryable
Skip(pages * pageSize).Take(pageSize);
ObjectSet and ObjectQuery implement OrderBy(string columnName), and this code compiles, but yields the error:
Unable to create a constant value of type 'DataModel.Parent'. Only
primitive types ('such as Int32, String, and Guid') are supported in
this context.
Of course, I can get the parent ID, but the Child.ParentReference is also a non-primitive type.
I can think of a few ways that would result in loading the entire recordset across the wire, but I feel like I must be missing something, because it must not be so hard to get a set of basic directive through to the database using all MS-centric technologies.
edit: pretend I'm http://en.wikipedia.org/wiki/Quiverfull , and need to paginate my children. :)
edit2: clarified my need to query a dynamic column name.
var parents = db.Parents; // Do whatever you need to get your unsorted collection from EF here.
if (sortBy == "Gender")
{
parents = parents.OrderBy(p => p.Gender);
}
else if (sortBy == "FirstName")
{
parents = parents.OrderBy(p => p.FirstName);
}
Now, this obviously isn't sorting on multiple columns, just a single column. And you can add in more logic for sort direction as well.
Edit: took out the crap about PredicateBuilder, I was going the wrong way when I started typing this answer, and forgot to take out the old stuff.
Try replacing your OrderBy
OrderBy("age", ListSortDirection.Ascending).
with
OrderBy(x => x.Age).
also the Where
Where(c => c.Parent == Parent && c.Gender = 'm').
should read
Where(c => c.Parent == Parent && c.Gender == 'm').
So there were a couple issues I was having, both mentioned in the question title.
Sorting by a run-time-selected, or dynamic, column name required some expression building. I used #Slace's popular extension method here.
That required an IQueryable. IQueryable works for me, because every time I was accidentally transforming my query into an enumerable, I was of course bringing all the results back over the wire before paging, which I was trying to avoid. But I still needed a way to get an IQueryable for results with a relationship to an entity I already held.
It was something simple I overlooked, just joining on the Entity.Id worked, and didn't result in redundant joins at the datasource. Not quite as object-oriented as I expected from EF, but it will do.
Repository. // Repository
Children. // ObjectSet
Where(c => c.Parent.Id == Parent.Id). // ObjectQuery, works fine
OrderBy(columnName, ListSortDirection.Ascending). // IOrderedQueryable
Skip(pages * pageSize).Take(pageSize); // Only transfers 1 page
I'm currently doing integration testing on a database and I have the following sql statement:
var date = DateTime.Parse("01-01-2010 20:30:00");
var result = datacontext.Repository<IObject>().Where(r => r.DateTime > date).First();
Assert.IsFalse(result.Finished);
I need to test if the results retrieved from the statement, where the given date is less then the date of the object, have Finished set to False. I do not know how many results I get back and currently I'm getting the first object of the list and check if that object has Finished set to false. I know testing only the first item of the list is not valid testing, as a solution for that I could iterate through the list and check all items on Finished, but putting logic in a Test is kinda going against the concept of writing 'good' tests.
So my question is:
Does anyone have a good solution of how to properly test the results of this list?
You can go the other way around, check if you have any result in that date range that is finished.
If there is any, then your test should fail.
I can't test any fancier code, so I'll give you a simple way:
int noOfResultsFinished = datacontext.Repository<IObject>()
.Where(r => r.DateTime > date && r.Finished).Count();
if (noOfResultsFinished > 0)
{
// fail test
}
I'm trying to retrieve a user object from a foreign key reference but each time I try to do so nothing gets returned...
My table is set up like this:
FBUserID long,
UserID uniqueidentifier
so I have my repository try to get the User when it's provided the FBUserID:
public User getUserByFBuid(long uid)
{
User fbUser = null;
IEnumerable<FBuid> fbUids = _myEntitiesDB.FBuidSet.Where(user => user.FBUserID == uid);
fbUser = fbUids.FirstOrDefault().aspnet_Users;
return fbUser;
}
I've checked that the uid (FBUserID) passed in is correct, I've check that the UserID is matched up to the FBUserID. And I've also checked to make sure that fbUids.Count() > 0...
I've returned fbUids.FirstOrDefault().FBUserID and gotten the correct FBUserID, but any time I try to return the aspnet_Users or aspnet_Users.UserName, etc... I don't get anything returned. (I'm guessing it's getting an error for some reason)
I don't have debugging set up properly so that's probably why i'm having so much troubles... but so far all the checking I've done I've been doing return this.Json(/* stuff returned form the repository */) so that I can do an alert when it gets back to the javascript.
Anyone know why I would have troubles retrieving the user object from a foreign key relationship like that?
Or do you have any suggestions as to finding out what's wrong?
For now, with Entity Framework 1, you don't get automatic delayed loading, e.g. if you want to traverse from one entity to the next, you need to either do an .Include("OtherEntity") on your select to include those entities in the query, or you need to explicitly call .Load("OtherEntity") on your EntityContext to load that entity.
This was a design decision by the EF team not to support automagic deferred loading, since they considered it to be too dangerous; they wanted to make it clear and obvious to the user that he is also including / loading a second set of entities.
Due to high popular demand, the upcoming EF v4 (to be released with .NET 4.0 sometime towards the end of 2009) will support the automatic delayed loading - if you wish to use it. You need to explicitly enable it since it's off by default:
context.ContextOptions.DeferredLoadingEnabled = true;
See some articles on that new feature:
A Look at Lazy Loading in EF4
POCO Lazy Loading
Don't know if this is what you are asking but i do a join like so;
var votes = from av in dc.ArticleVotes
join v in dc.Votes on av.voteId equals v.id
where av.articleId == articleId
select v;
Did this help or am I off base?