Strange behavior on a code I'm trying to develop.
I'm not understanding if it is something with the DB / code / permissions.. or other.
What is happening is that after filling up a form, some specific values which should be 0 are being passed to the database as null. If I see directly on the database, they are set as null. One of the fields is an "int" and the other is a "boolean".
For this code I'm using C# with ASP.net and the Entity Framework. The database is Microsoft SQL.
What could be useful to try to find the issue here?
What could I be missing?
I've tried so far the following:
Changing settings on the database from accepting null values to not accept null values. With this when I try to save an object of this type, the object is not saved, as there are fields which are being passed as null. If I confirm with the debugger before the action to the Database, they are filled as 0 and not as null.
Tried to change the way the users are authenticated. No changes.
Rebuild the database with the previous settings. No changes.
Rebuild the solution with all the database connection. No changes.
Confirmed the methods / procedures to store and update the database, they seem to be correct.
Also, they work for the other fields in this object.
I've searched for some solutions here in stackoverflow and through the web, but until now, nothing has worked.
What else could I check to understand why the values reach the database as null?
The code:
string path = Server.MapPath("~/prod/ficheiros/") + uplFicheiro.FileName;
uplFicheiro.SaveAs(path);
videos v = new videos();
v.id = 21;
v.video_name = VideoName.Text;
v.desc = DescVideo.Text;
v.aprov = true; <--- reaches DB as null
v.username = Page.User.Identity.Name;
v.url = "45";
v.num_visualizacoes = 0; <--- reaches DB as null
AcessoDados.DBVideos.insertVideo(v);
GridView1.DataBind();
CleanForm();
The insertVideo:
[DataObjectMethod(DataObjectMethodType.Insert, true)]
public static bool insertVideo(videos vid)
{
bool res = false;
try
{
contexto.Entry(vid).State = System.Data.Entity.EntityState.Added;
res = (contexto.SaveChanges() != 0);
}
catch (Exception) { }
return res;
}
I found the problem. The method which is writing on the database is not including the fields which I'm seeing as null. Hence the reason for them to reach the DB as null.
I need to correct this part which was generated by the Entity Model. Is there any way for the model to be corrected instead of I writing the methods manually?
-You need to go to properties for the colu
- check there General block -> Default Value and Binding
- make sure you set it to 0 (zero)
- If it is blank it will take by defaulf NULL
Related
I've currently got a bit of an issue when trying to check values that have been posted as part of an update, to what is currently being held in the database.
Currently what i'm doing is reading the existing record into a new variable, alongside the one passed in from the post, and checking values in that variable. However I've just noticed that as soon as I read the record from the database, the values passed in from the post get reset to their previous value.
I have a feeling that the reason is that the posted record and the retrieved record both have the same primary key value, and so the code is then overwriting the new values as there can't be two different objects with the same primary key in memory. Though that is just a guess.
Can someone help me with this issue, and possibly help me find a way to get around this?
EDIT:
My code is below. This is the main code, and as soon as I retrieve the "original record", the values in the "faultrecord" get reverted to what they were before
[HttpPost]
public ActionResult Edit(fault faultrecord)
{
fault originalRecord = _faultRepository.Read(faultrecord.ID); /*here is where it gets reverted*/
if (faultrecord != originalRecord)
{
/*perform actions and update record*/
}
}
The below code is what I use to read the record from the database:
public fault Read(int id)
{
var result = ITJobEntities.faults.Where(t => t.ID == id);
if (result.Any())
{
return result.FirstOrDefault();
}
return null;
}
My only reason for believing it to be to do with the primary keys is because when I added in the "originalRecord" retrieval, my update statement to the database started failing due to there being multiple objects with the same ID (the actual error was a bit more descriptive, but I can't remember it fully).
The goal is simple. I need to update the LastUpdated column in the Schedule table. I've tried several different methods to achieve that goal but with no success. I'm certain the code is pointing to the correct database and I'm also checking the correct [local] database for the changes. When a break point is set on SaveChanges(), the code halts at that point. I can see that "db" contains the updated Date/Time information for the correct record. Yet, it does not save it to the database.
Having gone through Stack Overflow, I've tried some suggestions like using Attach and setting the Entity State [to Modified]. Neither of those suggestions worked. HasChanges returns false, even though I can see the change is applied to the context variable.
Also, the class this method is in contains other methods that have no problem accessing the database and doing some inserts. The below code is just three different attempts to give you an idea on how I'm trying to do it. Any suggestions would be greatly appreciated.
public static void UpdateLastUpdated(int scheduleId)
{
using (var db = new MyContext())
{
var schedule = from s in db.Schedule where s.Id == scheduleId select s;
schedule.FirstOrDefault().LastUpdated = DateTime.Now;
db.SaveChanges();
var schedule2 = db.Schedule.Find(scheduleId);
schedule2.LastUpdated = DateTime.Now;;
db.SaveChanges();
var schedule3 = db.Schedule.Single(s => s.Id == scheduleId);
schedule3.LastUpdated = DateTime.Now;
db.SaveChanges();
}
}
You must indicate the change
db.Entry(schedule3).State = EntityState.Modified;
or
db.Entry(schedule3).Property(x => x.LastUpdated).IsModified = true;
So as it turns out, after a lot of trial and error... The issue was because the column was computed. I tried updating another column in the same table from that method and it worked fine. Then I did some research on computed columns and found that to be the problem. After removing the annotation, the code works fine. Now I just need to figure out how to get the default value set without the annotation.
Thank you to everyone who offered solutions and comments. Much appreciated!
I have a table with about 150 rows in it. These are the data types in the table:
int (PK)
nvarchar(52)
tinyint
datetime
uniqueidentifier
nvarchar(300)
bit
bit
bit
bit
I download the data from a web service and insert into the database. When I do that it works fine.
I later in the execution of my program I call the web service again. Since I may have updated some of the data I downloaded the first time, I check the db to see the row has changed. If it has then I leave it, if not then I update it. I think it is the check to see if it is there that is causing me the problems. When I do it I get this error:
"SQL Server Compact has exceeded the buffer size. The default size can be increased on initialization by modifying the ssce: max buffer size property. [ The default size = 655360 ]"
NOTE: This does not happen right away on the second time around. (Meaning that I stepped through some rows and they updated just fine.)
The only thing I can think of is that my result set is not getting cleared out. (Though I have used the same code to access the database with no problems.)
Here is my code:
public static SqlCeResultSet SetupTable(string tableName, string indexName,
bool allowUpdates, params object[] whereValues)
{
// The command used to affect the data
var command = new SqlCeCommand
{
CommandType = CommandType.TableDirect,
Connection = _connection,
// Set the table that we are going to be working with.
CommandText = tableName,
// Indicate what index we are going to be using.
IndexName = indexName
};
if ((whereValues != null) && (whereValues.Length > 0))
command.SetRange(DbRangeOptions.Match, whereValues, null);
// Get the table ready to work with.
if (allowUpdates)
return command.ExecuteResultSet(
ResultSetOptions.Updatable | ResultSetOptions.Scrollable);
else
return command.ExecuteResultSet(ResultSetOptions.Scrollable);
}
The call looks something like this:
SetupTable("tblMyTable", "IndexName", true, whereValue);
The weird thing is that it all works fine if I don't use the SetRange. It seems to me that it should use less buffer space if I use a SetRange (not more as it seems to be doing).
After it crashes with this error calls in Query Analyzer will also give the same message. I could up my buffer size but I am sure it will just take a bit longer to fill up (especally because I am passing in a "where" value that sets the range to a single row).
One thing to note is that I call the above code for each row in my table. (That is why I am asking if I should be cleaning up my results.) While I do call it for each row in my table, the previous one goes out of scope before I make a new one.
Any help would be great!
(Note: if you want to see the full code for the SetupTable stuff I put the whole class here.)
Are you disposing your command somewhere?
Anything that implements IDisposable (has a Dispose() method) should be disposed. That's the general rule. Since you're calling this method for every row, you should dispose your command.
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?
C# and general programming noobie here.
I have two tables. Property and Memo. There can be many Memo's to a single Property. I have, at least I think I do, the format of the object creation done correctly. The issue I do have is the Memo object doesn't save with the Property object. The Property object seems to save just fine.
Since I am a stack-noobie, I cannot post images strait into the post, so I've uploaded a couple which show both my Entities Diagram and the Referential Constraint dialogue.
www.jmtland.com/Pics/Diagram.png
www.jmtland.com/Pics/Referential%20Constraint.png
MTDBEntities1 dc = new MTDBEntities1();
Property newProp = new Property();
newProp.Address = t_Address.Text.Trim();
newProp.City = t_City.Text.Trim();
newProp.State = t_State.Text.Trim();
newProp.Zip = t_Zip.Text.ToString();
newProp.PropertyType = cb_PropertyType.Text.Trim();
if (t_SizeMin.Text.Trim().Length != 0) { newProp.SizeMin = Convert.ToInt64(t_SizeMin.Text); } // SizeMin is not required, so it won't be passed to the DB if there is no value.
newProp.SizeMax = Convert.ToInt64(t_SizeMax.Text);
newProp.SizeMetric = cb_SizeType.Text.Trim();
if (t_PriceMin.Text.Trim().Length != 0) { newProp.PriceMin = Convert.ToDecimal(t_PriceMin.Text); } // PriceMin is not required, so it won't be passed to the DB if there is no value.
newProp.PriceMax = Convert.ToDecimal(t_PriceMax.Text);
newProp.LeaseType = cb_LeaseType.Text.Trim();
newProp.WebLink = t_WebLink.Text.Trim();
newProp.Deleted = false;
newProp.DateDeleted = null;
newProp.DateCreated = DateTime.Now;
Memo newMemo = new Memo();
newMemo.Memo1 = t_PropertyMemo.Text.Trim();
newMemo.MemoDateCreated = DateTime.Now;
newProp.Memos.Add(newMemo);
dc.AddToProperties(newProp);
dc.SaveChanges();
I've been searching around for a fix for this problem for the last two days on multiple forums. I've followed so many examples that I almost forgot my original code.
Sorry for the noobness.
Update:
I have tried saving the Property Table first, then the Memo table.
-Doesn't work either.
I have run through the debugger and there seems to be data associated with the Memo object as well as the Property object contains the Memo object in question but it, for some reason, doesn't save at the same time.
I've though about a different way around it, where I could save the property, then do a new query to get the PropertID of that new object, then force save the Memo object with the PropertyID returned.
The issue I have with that method is that would mean my understanding of the Entity framework wouldn't be correct. I'd probably be able to hack my way around it but if I can't get it to work properly from the beginning, I fear that my later implementation of the same tech will be hindered by my inability to get it right from the get go. I've dabbled in programming before and the one thing I've learned is if you don't learn the basics right the first time, the rest of your experience can be corrupted.
The comment from RPM1984 seems to have worked. I don't know why that worked over what I tried but whatever, I can now move onto my next 4 hour block of programming a single method!
Do you have a navigational property
called "Memos" on the "Property"
entity on your EDMX? I think the last
line should be
dc.Properties.AddObject(newProp) –
RPM1984 5 hours ago