Facing a strange problem with EF at the moment. I have a table in database with nvarchar(MAX) data type and is a nullable field. While updating the entries in the table when I assign null to this field its not saving that null, rather keeping the old value intact. But saving the empty string in it works.
My code looks like this,
myobject.field1 = null; // assigning **null** here.
dbcontext.update();
dbcontext.saveChanges();
Any solution or guidance will be really appreciated.
What I have tried:
UseCSharpNullComparisonBehavior
and
UseDatabaseNullSemantics
EDIT:
Found the culprit, Our application has Unit of Work and Repositories implemented and we have a base Repository which includes a update method like below,
public virtual void Update(T entity)
{
//Ensure only modified fields are updated.
_dbEntities.Set<T>().Attach(entity);
var dbEntityEntry = _dbEntities.Entry<T>(entity);
foreach (var property in dbEntityEntry.OriginalValues.PropertyNames)
{
var current = dbEntityEntry.CurrentValues.GetValue<object>(property);
if (current != null)
dbEntityEntry.Property(property).IsModified = true;
}
}
In this function, updation is restricted in the null case. Though In my opinion this logic is invalid as it does not let the user change the existing value to null if user wants to.
Would love to hear the expert's opinion on this.
Sorry to bother you all.I am new to this kind of advanced logics and that make me stuck.
Try do this:
myobject.field1 = null;
dbcontext.Entry(myobject).Property(x => x.field1).IsModified = true;
dbcontext.saveChanges()
Related
To all,
I'm new to LinqtoSql using C# in VS2015. The code (below) retrieves what I wish from the server table, performs the function SendSMS properly, however, I don't know how to update the DateTimeSent value in the underlying table. I look at the smsunsentline variable and intellisense says it is a local variable so I know I'm not using the linked variable I need to do the update. Any help welcome.
Greg
protected void SendQueueButton_Click(object sender, EventArgs e)
{
string smsexception;
SMSClassesDataContext dbContext = new SMSClassesDataContext();
var unsent = from SMSsent in dbContext.SMSsents where SMSsent.DateTimeSent == null select SMSsent;
foreach (SMSsent smsunsentline in unsent)
{
smsexception = "";
SendSMS(smsunsentline.To, smsunsentline.Message, ref smsexception);
smsunsentline.DateTimeSent = DateTime.Now;
dbContext.SubmitChanges();
}
}
Does your SMSSent class have one (or more) fields flagged as members of the table's primary key?
Even if the underlying table doesn't have a primary key, L2S needs to have a set of members that can be treated as a primary key for the purpose of identifying the record that is going to be updated. If no members are marked as members of the primary key, it will not be able to update records.
Your code seems okay, you should probably wrap in a using Statement
using(var context = new SMSClassesDataContext()) {
var unsentsms = context.SMSsents.Where(x => x.DateTimeSent == null);
foreach(var sms in unsentsms) {
SendSMS(sms.To, sms.Message, out string smsexception);
sms.DateTimeSent = DateTime.Now;
context.SubmitChanges();
}
}
I believe this is asked somewhere else but I can't find straight solution.
My Api is passing object model and on the server side every value of that object which is not passed is considered null (makes sense).
Is there way I can tell EF6 not to update entity with null values from passed object in manner I don't have to write each property and check if it's null.
Pseudo code
API
Update(int id, TaskEntity obj)
{
unitOfWork.Tasks.Update(id, userTask);
...
unitOfWork.Save()
}
Repo update
Update(int id, T entity)
{
var existingRecord = Get(id); //Gets entity from db based on passed id
if (existingRecord != null)
{
var attachedEntry = Context.Entry(existingRecord);
attachedEntry.CurrentValues.SetValues(entity);
}
}
My problem is that any data with null values will actually rewrite existing db record value with nulls.
Please point me to a solution or article where this is solved. Should I go reflections, maybe automapper could handle this (it's not its purpose i believe), or some kind of helper method should be written, as my objects can contain sub object.
Thank you in advance.
You can do something like this
Update(int id, T entity,string[] excludedFields)
{
var existingRecord = Get(id); //Gets entity from db based on passed id
if (existingRecord != null)
{
var attachedEntry = Context.Entry(existingRecord);
attachedEntry.CurrentValues.SetValues(entity);
for(var field in excludedFields)
{
attachedEntry.Property(field).IsModified = false;
}
}
}
some scenaries requires you to update part of the object and sometimes other parts, the best way in my opinion is to pass the fields to exclude from the update
hope it will help you
Personally not a big fan of hitting database and doing a get operation before doing an update. May be while doing the ajax call, you can send a list of properties which you should update (so that the scenario where updating to null values (erasing existing ones) will also be handled).
I'm doing small modifications to what #Hadi Hassan has done (without hitting database for getting the entity):
Update(T entity,string[] includedFields)
{
var existingRecord = Context.Attach(entity); // assuming primary key (id) will be there in this entity
var attachedEntry = Context.Entry(existingRecord);
for(var field in includedFields)
{
attachedEntry.Property(field).IsModified = true;
}
}
Note - attachedEntry.Property(field).IsModified will not work for related entities
I searched vigorously for an answer to this, but I was unable to find (or understand) a solution. I have a query where I am joining to another table that may or may not have associated records. Here is the query:
var educationUniversity = result.new_educationUniversity.Select(c => new
{ c.majorDegree, c.dateEnd, c.dateStart, c.institutionName,
c.degreeProgramCompletionStatus, c.institutionAddress,
attachmentId = c.attachmentId ?? 0,
fileName = c.new_attachments.fileName ?? "No Attachment"}).ToList();
The first table is "new_educationUniversity" and it holds details of a user's college or university degree. The user may or may not have uploaded an attachment (which is stored in the "new_attachments" table). The attchmentID is the primary key in the "new_attachments" table and a foreign key in the "new_educationUniversity" table. EF sees the relationship.
I am binding the results to a repeater but the code fails on the line above if there is no related attachment. Everything works fine if there is an attachment or if I remove the reference to the fileName.
Above, I am handling if the fileName is NULL (or at least I am trying to), but I suspect my issue is that the record simply doesn't exist, which is different from NULL I guess. I've tried using something like: c.new_attachments.fileName.SingleOrDefault() or DefaultIfEmpty() with no luck.
As an analogy, imagine you have a CUSTOMERS table and an ORDERS table. You want to query the following:
-customer last name
-customer first name
-customer most recent order Id
However, you have registered customers who have never purchased anything. I'm sure I am doing something completely noobish, so any assistance is GREATLY appreciated. Thanks!
So you have a few things going on here:
You can get a null reference exception on your reference to c.new_attachments.fileName. If new_attachments is null, then this will throw an exception. Including the null-coalescing operator (the ??) won't help, because you're trying to access the property of something which can be null.
Unless you're lazy-loading (generally bad), then there's no reason for you to be trying to create a dynamically typed object to send to your repeater. Just pass the result.new_educationUniversity object directly.
What's the solution?
I'd create a partial class to add a new property to your new_educationUniversity class. Add a null-reference-safe property reference to determine the file name of the new_attachments property of new_educationUniversity. Then, bind the repeater to your new property. Something like:
public partial class new_educationUniversity {
public String AttachmentFileName {
get {
if (new_attachments == null)
return "";
else
return new_attachments.fileName;
}
}
}
The following line of code seems to be working.
var educationUniversity = result.new_educationUniversity.Select
(c => new { c.majorDegree, c.dateEnd, c.dateStart, c.institutionName,
c.degreeProgramCompletionStatus, c.institutionAddress, attachmentId = c.attachmentId ?? 0,
fileName = (c.new_attachments == null ? "***NO ATTACHMENT***" : c.new_attachments.fileName)}).ToList();
I don't fully understand what this line means:
fileName = (c.new_attachments == null ? "***NO ATTACHMENT***" : c.new_attachments.fileName)}
I assume it says "if nothing is there replace with the string "NO ATTACHMENT" otherwise use what is in the DB"
Is this acceptable? So far, so good. Thanks!
I'm having a very weird bug, that only seems to happen on a particular item I'm trying to update in the DB, using entity framework.
Here is my code:
var shoppingCartItem = GetShoppingCartItemById(shoppingCartItemId);
shoppingCartItem.Quantity = newQuantity;
_context.SaveChanges();
and this is the method that gets the item from the DB before updateing:
public ShoppingCartItem GetShoppingCartItemById(int shoppingCartItemId)
{
if (shoppingCartItemId == 0)
return null;
var query = from sci in _context.ShoppingCartItems
where sci.ShoppingCartItemId == shoppingCartItemId
select sci;
var shoppingCartItem = query.SingleOrDefault();
return shoppingCartItem;
}
This code works on some items, but doesn't on a particular one I'm testing with now. If I check the state of the object (using _context.ObjectStateManager.GetObjectStateEntry(shoppingCartItem)) after changing the property Quantity it's Unchanged :(
Has this ever happens to any of you? Any idea why this happens, or what could be causing this?
I have had a similar problem while passing the data object to a view, then getting it back again - in this case it breaks the link to the datacontext. this shouldnt happen in this case, but setting the EntityState to Modified and re-attaching it worked for me, it may be worth trying for you.
var shoppingCartItem = GetShoppingCartItemById(shoppingCartItemId);
shoppingCartItem.Quantity = newQuantity;
_context.Entry(shoppingCartItem).State = System.Data.EntityState.Modified;
_context.SaveChanges();
Note however that this only works with EF4.1 - I had to update to 4.1 just to get an easy way to edit items!
I am thinking about how to use Linq in the classic 3-tier archetecture of .net project. Apprently, Linq to SQL should appear in Data tier. The reason I choose Linq is because it will save me much time on code than using store procedure. I did some search on line about the insert/update/delete method of Linq, but didn't find an appropriate method for record update using entities. Usually, people will do update using this way:
public void UpdateUser(String username, String password, int userId)
{
using (var db = new UserDataContext()){
var user = db.user.Single(p => p.Id = userId);
user.Username = username;
user.Password = password;
db.SubmitChanges();
}
}
Why we don't use entity to pass the record like this:
public void Update(Application info)
{
VettingDataContext dc = new VettingDataContext(_connString);
var query = (from a in dc.Applications
where a.Id==info.Id
select a).First();
query = info;
try{
dc.SubmitChanges();
}
catch(Exception e){
//...
}
}
But unfortunately, the above code is wrong because of "query=info", but if I assign each value from "info" to "query", it works fine. like
query.firstName=info.firstName;
query.lastName=info.lastName;
So if this table have 40 fields, I have to write 40 lines code. Is there any easier way to do the update? Hope I describe this issue clearly.
Adding another answer as a comment was not sufficient to expand on my previous answer.
Lets take a step back and look at what you want to do here from a logical perspective. You want to tell your data access layer how it should update the database, with all the new/changed values it needs to write.
One very common way of doing this is to pass an entity which has those changes (which is what you're doing in your example). This can become tricky, as you have seen, because if you simply overwrite the entity variable with the changed entity, Linq2Sql will lose change tracking... just because the new entity is assigned to the same variable, doesn't mean that Linq2Sql automatically picks up changes from the new object... in fact Linq2Sql has no knowledge of the new object at all...
Example:
// In domain layer:
MyEntity entity = new MyEntity();
entity.PrimaryKey = 10;
entity.Name = "Toby Larone";
entity.Age = 27;
myDataRepository.Update(entity);
// In data layer:
void Update(MyEntity changedEntity)
{
using (var db = new DataContext())
{
var entity = (from e in db.MyEntities
where e.PrimaryKey == changedEntity.PrimaryKey
select e).First();
// Linq2Sql now has change tracking of "entity"... any changes made will be persisted when SubmitChanges is called...
entity = changedEntity;
// Linq2Sql does **not** have change tracking of changedEntity - the fact that it has been assigned to the same variable that once stored a tracked entity does not mean that Linq2Sql will magically pick up the changes...
db.SubmitChanges(); // Nothing happens - as far as Linq2Sql is concerned, the entity that was selected in the first query has not been changed (only the variable in this scope has been changed to reference a different entity).
}
}
Now you've already seen that assigning each field to the entity rather than replacing it works as intended - this is because the changes are being made to the original entity, which is still inside the Linq2Sql change tracking system..
One possible solution to this problem would be to write a method that "applies" the changes of another Entity to an existing one, ie:
partial class MyEntity
{
void ApplyChanges(MyEntity changedEntity)
{
this.PrimaryKey = changeEntity.PrimaryKey;
this.Name = changedEntity.Name;
this.Age = changedEntity.Age;
}
}
and then your data access would look like this:
// In data layer:
void Update(MyEntity changedEntity)
{
using (var db = new DataContext())
{
var entity = (from e in db.MyEntities
where e.PrimaryKey == changedEntity.PrimaryKey
select e).First();
// Linq2Sql now has change tracking of "entity"... any changes made will be persisted when SubmitChanges is called...
entity.ApplyChanges(changedEntity);
db.SubmitChanges(); // Works OK...
}
}
But im sure you don't like this solution - because all you have done is effectively move the repetitive field assignment out of the repository and into the Entity class itself...
Going back to the logical perspective - all you really need to do is tell the data access repository 2 things - 1) which record you want to update and 2) what the changes are. Sending an entirely new entity which encapsulates those two requirements is not necessary to achieve that goal, in fact I think it's very inefficient.
In the following example, you are sending the data repository only the changes, not an entire entity. Becuase there is no entity, there are no change tracking issues to work around
Example:
// In domain layer:
myDataRepository.Update(10, entity =>
{
entity.Name = "Toby Larone";
entity.Age = 27;
});
// In data layer:
void Update(int primaryKey, Action<MyEntity> callback)
{
using (var db = new DataContext())
{
var entity = (from e in db.MyEntities
where e.PrimaryKey == primaryKey
select e).First();
// Linq2Sql now has change tracking of "entity"... any changes made will be persisted when SubmitChanges is called...
// The changes that were sent are being applied directly to the Linq2Sql entity, which is already under change tracking...
callback(entity);
db.SubmitChanges();
}
}
In the previous examples, the field assignments were happening twice - once when you described the changes you wanted to make, and again in the data repository when you needed to apply those changes to a Linq2Sql change tracked entity.
Using the callback, the field assignments only happen once - the description of the change itself is what updates the tracked entity.
I hope I explained this well enough :)
Think about what the data repository actually requires in order to perform the update. It does not require an object that contains those changes, but a description of what changes need to be made. This can be encapsulated easily into a callback delegate...
public void UpdateUser(int userId, Action<User> callback)
{
using (var db = new DataContext())
{
User entity = db.Users.Where(u => u.Id == userId).Single();
callback(entity);
db.SubmitChanges();
}
}
myrepository.UpdateUser(userId, user =>
{
user.Username = username;
user.Password = password;
// etc...
});
query is not the same type as info. They may have the same properties to you, but the code doesn't know that.
Now, if you want to avoid writing a bunch of unnecesary code, you can use a third party library like AutoMapper which can do that for you.