LINQ not updating on .SubmitChanges() - linq

Is there any reason something like this would not work?
This is the logic I have used many times to update a record in a table with LINQ:
DataClasses1DataContext db = new DataClasses1DataContext();
User updateUser = db.Users.Single(e => e.user == user);
updateUser.InUse = !updateUser.InUse;
db.Log = new System.IO.StreamWriter(#"c:\temp\linq.log") { AutoFlush = true };
db.SubmitChanges();
(updateUser.InUse is a bit field)
For some reason it isn't working. When I check the linq.log it is completely blank.
Could there be a problem with my .dbml? Other tables seem to work fine but I've compared properties in the .dbml and they all match.
It's as if the db.SubmitChanges(); does not detect any updates being required.

The table could not be updated properly because it had no primary key. (Actually it had the column but the constraint was not copied when I did a SELECT INTO my dev table). The DataContext class requires a primary key for updates.

Is the InUse property a "normal" one as far as LINQ is concerned? (e.g. it's not autogenerated or anything funky like that?)
Alternatively, I don't suppose it's a Nullable<bool> is it, with a current value of null? If so, your update line isn't actually doing anything - for nullable Booleans, !null = null.

Related

Getting max value on server (Entity Framework)

I'm using EF Core but I'm not really an expert with it, especially when it comes to details like querying tables in a performant manner...
So what I try to do is simply get the max-value of one column from a table with filtered data.
What I have so far is this:
protected override void ReadExistingDBEntry()
{
using Model.ResultContext db = new();
// Filter Tabledata to the Rows relevant to us. the whole Table may contain 0 rows or millions of them
IQueryable<Measurement> dbMeasuringsExisting = db.Measurements
.Where(meas => meas.MeasuringInstanceGuid == Globals.MeasProgInstance.Guid
&& meas.MachineId == DBMatchingItem.Id);
if (dbMeasuringsExisting.Any())
{
// the max value we're interested in. Still dbMeasuringsExisting could contain millions of rows
iMaxMessID = dbMeasuringsExisting.Max(meas => meas.MessID);
}
}
The equivalent SQL to what I want would be something like this.
select max(MessID)
from Measurement
where MeasuringInstanceGuid = Globals.MeasProgInstance.Guid
and MachineId = DBMatchingItem.Id;
While the above code works (it returns the correct value), I think it has a performance issue when the database table is getting larger, because the max filtering is done at the client-side after all rows are transferred, or am I wrong here?
How to do it better? I want the database server to filter my data. Of course I don't want any SQL script ;-)
This can be addressed by typing the return as nullable so that you do not get a returned error and then applying a default value for the int. Alternatively, you can just assign it to a nullable int. Note, the assumption here of an integer return type of the ID. The same principal would apply to a Guid as well.
int MaxMessID = dbMeasuringsExisting.Max(p => (int?)p.MessID) ?? 0;
There is no need for the Any() statement as that causes an additional trip to the database which is not desirable in this case.

Linq to entity update query not updating the table

Its just a simple Linq to Entity update query i tried with the following code but it doesn't update the "User" column in the DB.
Its not even throwing any exception also,please some one point me what am missing here.
MyEntities db = new MyEntities ();
var query = from SEVTs in db.SEVTs
where SESID == "4747747"
select SEVTs;
foreach (var SEVTs in query) {
SEVTs.USER = "Test";
}
db.SaveChanges();
Quite interesting, when i try the follwing query in the sql server its not update the record
update Schedwin.SEVT
set
USER3='Test'
Where
SESID='4747747' // here i pass the value as a string
SESID data type is CHAR and its a primary key. if i pass the value as SESID=4747747 then it update that record.
Please ignore my question.
Here what i missed my input value SESID == "4747747" //this have whitespace that's why it didn't updated that particular record.
Thanks All
You are nor modifying SEVTs.USER, but some local variable.
(BTW: create a context in a using construct)

Table with a foreign key

how can I build a table of "orders" containing "IdOrder", "Description" and "User"?... the "User" field is a reference to the table "Users", which has "IdUser" and "Name". I'm using repositories.
I have this repository:
Repository<Orders> ordersRepo = new OrderRepo<Orders>(unitOfWork.Session);
to return all Orders to View, I just do:
return View(ordersRepo.All());
But this will result in something like:
IdOrder:1 -- Description: SomeTest -- User: UserProxy123ih12i3123ih12i3uh123
-
When the expected result was:
IdOrder:1 -- Description: SomeTest -- User: Thiago.
PS: I don't know why it returns this "UserProxy123ih12i3123ih12i3uh123". In Db there is a valid value.
The View:
It is showed in a foreach (var item in Model).
#item.Description
#item.User //--> If it is #item.User.Name doesn't work.
What I have to do to put the Name on this list? May I have to do a query using LINQ - NHibernate?
Tks.
What type of ORM are you using? You mention "repositories" but does that mean LinqToSql, Entity Framework, NHibernate, or other?
It looks like you are getting an error because the User field is not loaded as part of the original query. This is likely done to reduce the size of the result set by excluding the related fields from the original query for Orders.
There are a couple of options to work around this:
Set up the repository (or context, depending on the ORM) to include the User property in the result set.
Explicitly load the User property before you access it. Note that this would be an additional round-trip to the database and should not be done in a loop.
In cases where you know that you need the User information it would make sense to ensure that this data in returned from the original query. If you are using LinqToSql take a look at the DataLoadOptions type. You can use this type to specify which relationships you want to retrieve with the query:
var options = new DataLoadOptions();
options.LoadWith<Orders>(o => o.User);
DataContext context = ...;
context.LoadOptions = options;
var query = from o in context.Orders
select o;
There should be similar methods to achive the same thing whatever ORM you are using.
In NHibernate you can do the following:
using (ISession session = SessionFactory.OpenSession())
{
var orders = session.Get<Order>(someId);
NHibernateUtil.Initialize(orders.User);
}
This will result in only two database trips (regardless of the number of orders returned). More information on this can be found here.
In asp.net MVC the foreign key doesn't work the way you are using it. I believe you have to set the user to a variable like this:
User user = #item.User;
Or you have to load the reference sometimes. I don't know why this is but in my experience if I put this line before doing something with a foreign key it works
#item.UserReference.load();
Maybe when you access item.User.Name the session is already closed so NHib cannot load appropriate user from the DB.
You can create some model and initialize it with proper values at the controller. Also you can disable lazy loading for Orders.User in your mapping.
But maybe it is an other problem. What do you have when accessing "#item.User.Name" from your View?

LINQ - Update null integer data field

I have got a field with data type int? price and allow null, when I set
book.price = null;
and update, it is not saved and does not throw any exceptions, when I change value # null, it is ok. I want set it null.
Make sure the field is nullable in the database and is reflected so in the dbml.
Regenerate the dbml for the table just to be sure. (Drop tabel from dbml and add again)
All I can say is it works for us so this is very strange.
I am not suer I understand the question, this part is unclear:
"when I change value # null, it is ok"
Did you make sure to call
db.SaveChanges();
(where [db] is the name of your Entites object)
It is a simple mistake that I make often :P

LINQ to SQL -

I'm attempting to use LINQ to insert a record into a child table and I'm
receiving a "Specified cast is not valid" error that has something to do w/
the keys involved. The stack trace is:
Message: Specified cast is not valid.
Type: System.InvalidCastException
Source: System.Data.Linq TargetSite:
Boolean
TryCreateKeyFromValues(System.Object[],
V ByRef) HelpLink: null Stack: at
System.Data.Linq.IdentityManager.StandardIdentityManager.SingleKeyManager2.TryCreateKeyFromValues(Object[]
values, V& v) at
System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache2.Find(Object[]
keyValues) at
System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType
type, Object[] keyValues) at
System.Data.Linq.CommonDataServices.GetCachedObject(MetaType
type, Object[] keyValues) at
System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation
assoc, Object instance) at
System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
at
System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode
failureMode) at
System.Data.Linq.DataContext.SubmitChanges(ConflictMode
failureMode) at
System.Data.Linq.DataContext.SubmitChanges()
(.....)
This error is being thrown on the following code:
ResponseDataContext db = new ResponseDataContext(m_ConnectionString);
CodebookVersion codebookVersion = db.CodebookVersions.Single(cv => cv.VersionTag == m_CodebookVersionTag);
ResponseCode rc = new ResponseCode()
{
SurveyQuestionName = "Q11",
Code = 3,
Description = "Yet another code"
};
codebookVersion.ResponseCodes.Add(rc);
db.SubmitChanges(); //exception gets thrown here
The tables in question have a FK relationship between the two of them.
The parent table's column is called 'id', is the PK, and is of type: INT NOT NULL IDENTITY
The child table's column is called 'responseCodeTableId' and is of type: INT NOT NULL.
codebookVersion (parent class) maps to table tblResponseCodeTable
responseCode (childClass) maps to table tblResponseCode
If I execute SQL directly, it works. e.g.
INSERT INTO tblResponseCode
(responseCodeTableId, surveyQuestionName, code, description)
VALUES (13683, 'Q11', 3, 'Yet another code')
Updates to the same class work properly. e.g.
codebookVersion.ResponseCodes[0].Description = "BlahBlahBlah";
db.SubmitChanges(); //no exception - change is committed to db
I've examined the variable, rc, after the .Add() operation and it does, indeed, receive the proper responseCodeTableId, just as I would expect since I'm adding it to that collection.
tblResponseCodeTable's full definition:
COLUMN_NAME TYPE_NAME
id int identity
responseCodeTableId int
surveyQuestionName nvarchar
code smallint
description nvarchar
dtCreate smalldatetime
dtCreate has a default value of GetDate().
The only other bit of useful information that I can think of is that no SQL
is ever tried against the database, so LINQ is blowing up before it ever
tries (hence the error not being a SqlException). I've profiled and verified
that no attempt is made to execute any statements on the database.
I've read around and seen the problem when you have a relationship to a non PK field, but that doesn't fit my case.
Can anyone shed any light on this situation for me? What incredibly obvious thing am I missing here?
Many thanks.
Paul Prewett
Post up the schema of the parent table.
if you look here, some other people have had your problem.
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3493504&SiteID=1
It appears that Linq2SQL has trouble mapping some foreign keys to some primary keys. One guy had a resolution, but I think you are already mapping to an IDENTITY column.
Since the database isn't being called I think you have to look at the mappings linq to sql is using. What does the Association look like? There should be an Association on both the parent and child classes.
Take a look at the linq to sql Association between the two classes. The Association should have a ThisKey property. The cast that is failing is trying to cast the value of the property that ThisKey points to, I think.
As far as I can tell there can be a problem when there is more than one key and the type of the first key does not match the type that ThisKey points too. I'm not sure how linq would determine what the first key is.
From the looks of it you only have one key and one foreign key so that shouldn't be the problem, but the designer, if you are using it, has been known to get creative.
I'm pretty much guessing, but this looks like something I've seen before.
Is this an example of this bug? If so, try running your code in .NET 4.0 now that the beta is out.
If, like me, you aren't ready to start using the beta, you may be able to work around the problem. The issue seems to be that LINQ does not properly support relationships defined on non-primary key fields. However, the term "primary key" does not refer to the primary key defined on the SQL table, but the primary key defined in the LINQ designer.
If you dragged your tables into the designer, then Visual Studio automatically inspects the primary key defined in the database and marks the corresponding class field(s) as "primary keys". However, these do not need to correspond to each other. You can remove the key Visual Studio chose for you, and pick another field (or group of fields). Of course, you need to make sure this is logical (you should have a unique constraint in the database on the field/fields you choose).
So I had 2 tables/classes related to eachother using an alternative key. The parent table had 2 keys: a surrogate primary key defined as an int, and an alternative natural key defined as a string. In the LINQ designer, I had defined the association using the alternative key, and I experienced the InvalidCastException whenever trying to update that association field on the child object.
To work around this, I went into the LINQ designer, selected the int, and then changed the Primary Key property from True to False. Then I chose the string, and set it's Primary Key property to True. Recompiled, retested, and the InvalidCastException is gone.
Looking at your screen shot it looks like you may be able to fix your issue by changing the LINQ primary key on ResponseCode from ResponseCode.ID to ResponseCode.ResponseCodeTableID
ResponseCode rc = new ResponseCode()
{
SurveyQuestionName = "Q11",
Code = 3,
Description = "Yet another code"
};
and:
INSERT INTO tblResponseCode
(responseCodeTableId, surveyQuestionName, code, description)
VALUES (13683, 'Q11', 3, 'Yet another code')
Are not the same, you are not passing in the foreign key reference. Now, I'm huge n00b at LINQ2SQL, but I'd wager that LINQ2SQL is not smart enough to do that for you, and it expects it as the first parameter of the anonymous dictionary, and is trying to cast a string to an integer.
Just some ideas.
This block:
codebookVersion.ResponseCodes.Add(rc);
db.SubmitChanges(); //exception gets thrown here
Can you try InsertOnSubmit instead of Add? i.e.
codebookVersion.ResponseCodes.InsertOnSubmit(rc);
I think Add is not meant to be used to insert records if my memory serves me right. InsertOnSubmit is the one to use.
To try and narrow down the culprit.
Have you tried replacing the anonymous dictionary with something like:
ResponseCode rc = new ResponseCode();
rc.SurveyQuestName = "Q11";
rc.Code = 3;
rc.Description = "Yet Another Code";
I've yet to really work with .NET 3.5 yet (day job is still all 2.0), so I'm wondering if there is an issue with passing the data using the anonymous dictionary (The cases don't match the SQL Columns for one).
Yea, I've read that and other posts, but it always seems to involve someone linking up to a field that simply has a unique contraint. Or in this guy's case (which does sound exactly like mine), he didn't get a solution.
Here's the parent table:
tblResponseTable definition (which maps to CodebookVersion)
COLUMN_NAME TYPE_NAME
id int identity
versionTag nvarchar
responseVersionTag nvarchar
versionTag does have a unique contraint on it, but that's not represented anywhere that I can see in the LINQ-to-SQL stuff - and since nothing ever goes to the database... still stuck.
Mike, I hear you. But no matter where I look, everything looks correct. I've checked and rechecked that the ResponseTableId is an int and that Id is an int. They're defined as such in the designer and when I go look at the generated code, everything again appears to be in order.
I've examined the associations. Here they are:
[Table(Name="dbo.tblResponseCode")]
public partial class ResponseCode : ...
...
[Association(Name="CodebookVersion_tblResponseCode", Storage="_CodebookVersion", ThisKey="ResponseCodeTableId", OtherKey="Id", IsForeignKey=true)]
public CodebookVersion CodebookVersion
{
...
}
[Table(Name="dbo.tblResponseCodeTable")]
public partial class CodebookVersion : ...
...
[Association(Name="CodebookVersion_tblResponseCode", Storage="_ResponseCodes", ThisKey="Id", OtherKey="ResponseCodeTableId")]
public EntitySet<ResponseCode> ResponseCodes
{
...
}
And a screenshot of the association in case that will help:
Any further thoughts?
ResponseCode rc = new ResponseCode()
{
CodebookVersion = codebookVersion,
SurveyQuestionName = "Q11",
Code = 3,
Description = "Yet another code"
};
db.ResponseCodes.InsertOnSubmit(rc);
db.SubmitChanges();
You may want to check to see that any fields in your database tables which are set by the db server when inserting a new record have that reflected in the Linq to SQL diagram. If you select a field on the Linq to SQL diagram and view its properties you will see a field called "Auto Generated Value" which if set to true will ensure all new records take on the default value specified in the database.
LINQ to SQL has been deprecated, FYI - http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx.
I ran into a very similar problem. I'll link you over to my wordy post: http://forums.asp.net/p/1223080/2763049.aspx
And I'll also offer a solution, just a guess...
ResponseDataContext db = new ResponseDataContext(m_ConnectionString);
CodebookVersion codebookVersion = db.CodebookVersions.Single(cv => cv.VersionTag == m_CodebookVersionTag);
ResponseCode rc = new ResponseCode()
{
ResponseCodeTableId = codebookVersion.Id,
SurveyQuestionName = "Q11",
Code = 3,
Description = "Yet another code"
};
db.ResponseCodes.InsertOnSubmit(rc);
db.SubmitChanges();
Somewhere in your object graph there is a conversion error, the underlying data model (or the Linq To SQL model) has changed. This is typically something like NVARCHAR(1) -> CHAR when it should be STRING, or something similar.
This error is not fun to hunt down, hopefully your object model is small.
We had a similar problem, caused by using non-integer keys. Details and hotfix number are here: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=351358

Resources