I have a multi-page (multi-view) form in MVC, the results of which will be saved to a single database table.
Code snippet that initializes the linq object in the first page of the form.
public ActionResult MyForm()
{
// returns a Linq object stored in session
Application currentApp = Application.FromSession();
// if null, initialize the object and save to session
if (currentApp == null)
{
currentApp = new Application();
currentApp.SessionSave();
}
return View(currentApp);
}
And here is a sample snippet of code for the final action that updates some data from the strongly-typed model, then triggers the database save.
[HttpPost]
public ActionResult MyForm3(Application app, FormCollection coll)
{
Application currentApp = Application.FromSession();
currentApp.Contact = app.Contact;
currentApp.AddFormToXml(coll);
currentApp.SessionSave();
_db.Applications.InsertOnSubmit(currentApp);
_db.SubmitChanges();
return RedirectToAction("Blah");
}
The problem I'm running into is that the SubmitChanges fails with the error
Cannot insert the value NULL into
column 'ApplicationData', table
'MyTable';
column does not allow nulls. INSERT
fails. The statement has been
terminated.
In this case, ApplicationData is a column of type xml, which LINQ interprets as an XElement object. When I set a breakpoint at SubmitChanges() and check the value of app.ApplicationData, it is clearly populated (non-null), and yet I continue to get this error. My only thought is that I am misunderstanding something with how data contexts work. It only seems to have an issue with this one column though. Is it possible that I need to figure out a way to attach the XElement object (ApplicationData) to my active data context (_db), and if so, how would I go about doing that?
Take a look at the actual SQL generated and sent to the server.
Start up SQL Server Profiler (on the tools menu in SQL Server Management Studio) and start a trace. Run your application until it crashes. Go back to SQL profiler and look at the SQL queries. Seeing things from the SQL end sometimes make it easy to spot the error, e.g. finding out if your are doing several inserts instead of just one.
Well my suggestion to you is to compare the data type of "ApplicationData" column in your Context model and in your database table.
Also please check your LINQ to SQL mappings for this column "AppliationData" again on the datatype itself.
Please update your post if you find anything...
Ok, so in the action method you mentioned can you check if you are calling the InsertOnSumbit Method again anywhere else before you are finally calling db.SubmitChanges()...or if you are calling the InsertOnSubmit method more than once... I think that will cause a problem if you are calling it twice on the same object.
Update:
I did tried a sample with a single table and was able to insert the xml data as mentioned below.
DataClassesDataContext ctx = new DataClassesDataContext();
Application a1 = new Application();
XName n = "dfdsf";
a1.ApplicationData = new XElement(n);
ctx.Applications.InsertOnSubmit(a1);
ctx.SubmitChanges();
so, now the question will be what does your column data looks like??? if you can post the sample content of the application data then it will be helpful. Also how are you setting the ApplicationData property value?
Related
I started working on a project in my work that doesn't have any documentation, and the person who developed the project in the first place isn't avalaible anymore.
There is this piece of code for doing and update to the database
_report = db.Report.Where(x => x.IdReport == ReportId).FirstOrDefault();
db.Report.Attach(_report);
_report.attr1 = reportmodel.attr1;
_report.attr2 = reportmodel.attr2;
_report.attr3 = reportmodel.attr3;
if (db.SaveChanges() != 0)
{
return View(reportmodel)
}
Looks fine and indeed does the update to the database in the table "Report", but additionally it is being inserted in another table "ReportLog" the detail of the change (orginal value, new value), I believe this is being done somehow in the SaveChanges().
So my question is where can I find where those insertions to the log table are being executed?
I have checked in the model if the table "Report" has some stored procedure mapped in the update action, checked for triggers and stored procedures in the database and used Find(Ctrl+f) to check for "ReportLog" in the entire solution, but I couldn't find where the insertion is being executed.
And something really weird is that this happens for the "Report" table only, using SaveChanges() for other updates in other tables does only what is expected
I found a trigger on the Report table that was doing the inserts
Querying using Linq in EF6 is giving old values while the database is having updated values
In the code below for the first run it works fine, But after the table tblReferenceNumber gets new rows, the query is returning only old values while I expect it to retrieve including the new records.
AuthDBEntities db = New AuthDBEntities()
tblReferenceNumber LRefNum = db.tblReferenceNumber.OrderByDescending(ab => ab.ID).First();
string lrNum = LRefNum.ReferenceNumber;
why I am getting the old values?
How can I fix it?
Each instance of DbContext has a cache. If you are using the same instance of db than the last time you got that record, then you will end up getting the cached data.
You can use:
db.Entry(LRefNum).Reload();
to force it to get fresh data.
More info about the caching here: http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/
But that also raises the question of why you are getting the same record twice with the same instance of db. Did you perhaps declare db as static?
When you use .First() you materialize this query and load data into memory.
So when u try to get values from LRefNum you refer to data in memory instead of database.
I'm trying to implement Server mode in one of Devexpress Grid in my application.
Grid view expects queryable source, so I don't want to use ToList() or AsEnumerable(loads all the data into app memory).
When I use AsQueryable I'm getting LINQ to Entities does not recognize the method...
Query details:
One of the column(Definition) in the table is stored as JSON string. I understand that it is trying to find SQL equivalent for Deserialize method, Please suggest if you know any alternatives..
Below is the query.
var requestList = (from request in db.request_def
let requestDefinition=new JavaScriptSerializer().Deserialize(request.Definition,typeof(RequestInfo))
let user = db.Users.FirstOrDefault(p => p.PRINCIPAL == requestDefinition.Principal)
let processingAccount =user.EMAIL
select new RequestModel
{
CreatedBy = request.CreatedBy
CreatedOn = request.CreateOn,
Status = request.Status,
ProcessingAccount = processingAccount,
}).OrderByDescending(p => p.CreatedOn).AsQueryable<RequestModel>();
You seem to be storing a JSON string in your database but you still want to "join" it to another table. Your options are probably limited to one of the following:
Drag the entire table into memory, deserialise and do your JOIN there. This would likely be horribly slow - don''t do this.
Move to a data store that is designed to be queried like this (i.e. MongodDB, DocumentDB etc.)
When you insert the JSON into your table, copy the value (i.e. Principal) into it's own column so you can do a classic SQL join, materialise the data in your code and then deserialise it.
If you are running SQL Server 2016 or newer then you should be able to run a raw SQL query against the database using SQL Server JSON query
Exclude the ProcessingAccount field from the query to be able to execute it on the server side and retrieve data. Add the Definition field to the RequestModel, instead. Then, add an unbound column in which you will manually load the ProcessingAccount data.
To do this, handle the CustomUnboundColumnData event. In the event handler, obtain the Definition of the current record using the ASPxGridColumnDataEventArgs.GetListSourceFieldValue method, deserialise it, and load User from the database to obtain the ProcessingAccount.
To reduce the amount of database queries, it is better to retrieve Definition value of all records in the current page and load all related Users in batch. You can do this on the first call of the CustomUnboundColumnData event handler, and store the result in a local variable to use it on subsequent calls.
I have a simple Linq query that is failing suddenly. This worked up until yesterday and I have not been able to determine the problem.
The query is simply getting a complete view from SQL Server
using(JobEntities JE = new JobEntities())
{
var BatchData = (from x in JE.vwBatchObjectActiveBatches select x).ToList();
}
Starting yesterday this line gets a
NullReferenceException (Object reference not set to an instance of an object)
My suspicion was that a user put in bad data causing the view to fail on SQL Server, but I have checked SQL Server itself and the view runs fine and populates with data.
This query was running in the middle of a larger function loading data from many places, so I have created a test case where I simply load the main window and run this query directly in the code behind to make sure that nothing else is affecting it, and the query still fails. All other Linq queries that I run in this project work still, only this one fails. The app is not under any production right now, and has been static for several months at least.
When I look at the JE in the watch window I can see the vwBatchObjectActiveBatches and it lists 164 records in the Local section -- this matches the view results on SQL Server. Expanding the Results View shows the null error again.
How can I find and fix whatever is causing this query to fail? Why does the results view show an error but the local Line shows the data that I am attempting to get?
It looks like your database returns NULL where Entity Framework does not expect/allow it. Data returned should be in accordance with the definition of its datamodel objects.
Solution: either 'fix' the data, or fix the query that produces it, or change the definition of your datamodel objects to allow NULL for the conflicting field(s).
I've got a SQL Server database that I'm trying to build a RESTful API for.
I'm using ADO.Net and Linq to retrieve a single row from a table like this:
[HttpGet]
public tTrip getTripById(Guid id)
{
var _trip = (from trips in db.tTrip
where trips.ID == id
select trips).FirstOrDefault();
return _trip;
}
When I debug the code the correct object is retrieved. If I keep running however, there will be no response. I'm guessing that's because for every foreign key present in the returned row, ADO does another lookup through the other mapped tables which slows down everything by a lot.
If I only select a single column that doesn't contain any FKCs everything works fine.
Any ideas how I can turn off the FKC lookup for that fetched object?
Thank you!
I found the problem - In the ObjectContext class (that's where the 'db' variable comes from btw), I had the ContextOptions.LazyLoadingEnabled variable set to true.
Set it to false and the application returns only the Guid for every entry instead of loading the entry details from the database.