I use Include() in EF but show me error that my object reference is not set - asp.net-mvc-2

I use the include Method in my asp.net mvc 2 project with EF 4.0
Here is my database structure.
Contact
ContactID
ContactName
AddressID (FK)
Address
AddressID
CodePostal
Street
A contact can contain an address or not.
In some case, I dont want any address. In that case, the AddressID in the contact table will be null.
I try to do this
_db.LocationContacts.Include("Contact.Address.City.Province.Country")
Thats give me an error if there is no address associate to the contact.
Is there a way to resolve that situation.
Thanks a lot.
This is the Error Message : System.NullReferenceException: Object reference not set to an instance of an object.

This line ...
var location = _db.LocationContacts
.Include("Contact.Address.City.Province.Country").First();
... does not throw a NullReferenceException. It happens later when you access location.Address.City or some other property or method of Address and Address is null (which is expected for some locations because it is allowed to have NULL values).
You just need to check if location.Address is null or not:
if (location.Address != null)
{
var city = location.Address.City; // OK
}
else
{
// var city = location.Address.City; // Not OK
}

Because you are accssing the City which is under Address which is null !
Use it like this
var contacts=_db.LocationContacts.Include("Contact.Address").ToList();
That gives you contacts with Address.

Related

Update an entity but not the null value properties

I have a customer which I want to update in the repository.
var customer = new Customer{ Name = "Test" }
The customer has still more properties which are null, because I have not loaded them before to the client. Thus these properties have all their default values like null or 0.
What do I have to do with latest EF 6, that only the property Name is updated and the other properties from the customer are not overwritten?
1.) How would I have to query/update the customer?
2.) What would happen if the customer has a collection of and he has changed some properties of some meetings - but not all properties - how would then be the override behavior?
UPDATE pseudo code
Open context
Get customer
Close context
Open context
Update customer.name
SAveChanges
Close context
The custom.name is not saved, why?
You can't do it natively without getting the whole entiy first, which is obviously 2 db hits.
There is however an extension you can use that does what you want:
https://github.com/loresoft/EntityFramework.Extended/wiki/Batch-Update-and-Delete
Assuming you already have your model generated and it has a name of "MyEntities" and you should have a customer ID if you are updating an existing. Here is a solution using c#.
using(MyEntities db = new MyEntities()) {
//this will retreieve the customer based on ID
Customer cust = db.Customers.FirstOrDefault(c => c.CustomerID == custID);
//you can update each column
cust.Name = "Test";
//save the changes to the entity
db.SaveChanges();
}

Set navigation property to null EF 6

I have two entities Inspection and User
An Inspection has an Approver property which is a User hooked up like so public virtual User Approver { get; set; }
Sometimes Approver has to be set to null
I am doing it as follows
Inspection rtrn = Context.Inspections.Where(x => x.Id == inspId).SingleOrDefault();
rtrn.Approver = null;
rtrn.ApprovalDate = new DateTime();
base.Update(rtrn); //EF repo
The problem is that this does not set Approver_Id to null in the database. In fact if I put a break point at the rtrn.ApprovalDate = new DateTime(); I can see that rtrn.Approver is still of type User. It looks as if it's ignoring the rtrn.Approver = null; line all together.
At the higher level I just want to break Inspection -- User association without deleting either entity.
Thank you!
Your virtual property is just that, virtual. It is filled with the record that matches its corresponding foreign key, which is typically ApproverId (unless you specified a different ForeignKey with the ForeignKey attribute).
If you want to get rid of the Approver, then you just need to set the ApproverId to null.

How to update only modified values (EntityFramework 5.0)?

I have this entity, want to update using entityframework
EmployeeModel employee = new EmployeeModel
{
Id = 1000, //This one must
FirstName = modifiedValue,
Email = modifiedValue,
LastName = originalValue,
Phone = originalValue
};
Code to update
_db.ObjectStateManager.ChangeObjectState(employee, EntityState.Modified);
_db.SaveChanges();
This is the SQL statement got once updated
Update Employee set Id=1138,FirstName='modifiedValue',Email='modifiedValue',LastName= 'OriginalValue',phone='originalValue' where Id=1138
But I am expecting this
Update Employee set FirstName='modifiedValue', Email='modifiedValue' where Id=1138.
I dont know what I am missing here. Please let me know.
This problem is common when dealing with DTOs. An employee entity is fetched from the database, mapped to a DTO and sent over the wire. The client then modifies this DTO and sends it back to the server.
When you touch (set) a property on an EF entity, EF will assume that the value has been changed. Even if the old value and the new value are exactly the same.
The same problem occurs when you map the DTO to a new Entity and attach it to EF and updating its status to 'Modified'.
Using AutoMapper:
// This will result in the full update statement
var employee = AutoMapper.Mapper.Map<EmployeeDto, Employee>(dto);
// This will result in a smaller update statement (only actual changes)
var employee = dbContext.Employees.Find(dto.Id);
AutoMapper.Mapper.Map(dto, employee);
Or, manually (I would avoid doing this, but just for the sake of completeness):
// This will result in a smaller update statement (only actual changes)
var employee = dbContext.Employees.Find(dto.Id);
if (employee.Email != dto.Email )
employee.Email = dto.Email;
There are probably some other ways for dealing with this problem... but using AutoMapper together with Entity Framework correctly is definitely one of the easiest ways.
This is the solution I got
var entity = _db.CreateObjectSet<Employee>();
entity.Detach(employee);
entity.Attach(employee);
foreach (string modifiedPro in employeeModel.ModifiedProperties){
_db.ObjectStateManager.GetObjectStateEntry(employee).SetModifiedProperty(modifiedPro);}
_db.SaveChanges();
Only modified values in the sql update statement
Update Employee set FirstName='modifiedValue', Email='modifiedValue' where Id=1138.
If anybody knows better answer than this, Please post your suggestions
You can try this way
public update(Person model)
{
// Here model is model return from form on post
var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();
var UpdatedObj = (Person) Entity.CheckUpdateObject(oldobj, model);
db.Entry(oldobj).CurrentValues.SetValues(UpdatedObj);
}
public static object CheckUpdateObject(object originalObj, object updateObj)
{
foreach (var property in updateObj.GetType().GetProperties())
{
if (property.GetValue(updateObj, null) == null)
{
property.SetValue(updateObj,originalObj.GetType().GetProperty(property.Name)
.GetValue(originalObj, null));
}
}
return updateObj;
}

Entity Framework 4.1 Code First - Unable to remove a relationship between two entities

I have a Supplier entity, each Supplier object may reference another Supplier object as its 'parent'.
public class Supplier
{
public int? Id { get; set; }
public virtual Supplier Parent { get; set; }
}
This all works as expected until I attempt to remove the relationship, as in, this supplier no longer has a parent. I can change it from null to a particular supplier and I can set it to a different supplier but setting it to null is not persisted after SaveChanges().
supplier.Parent = null;
The foreign key 'ParentId' in the Supplier table is set as nullable. Explicitly defining the relationship doesn't help.
modelBuilder.Entity<Supplier>().HasOptional(s => s.Parent).WithMany();
I'm sure I'm missing something obvious.
Just found another place in my code where I do the exact same thing (that works) and found this;
// Must access property (trigger lazy-loading) before we can set it to null (Entity Framework bug!!!)
var colour = modelItem.Colour;
modelItem.Colour = null;
Did the same in the new code and it all works.
Instead of just modelBuilder.Entity<Supplier>().HasOptional(s => s.Parent).WithMany(); use the following modelBuilder.Entity<Supplier>().HasOptional(s => s.Parent).WithMany().HasForeignKey(x=>x.ParentId);
Otherwise it has no idea what the foreign key's name is

Entity Framework - trying to insert null values when creating a new object

I'm having the same problem that a few of you have had - when trying to insert a new object, EF inserts null values for some of their properties, and the insert fails.
First let me describe the structure of our DB. Its an event management system, in which each event needs to be associated with a practice group, stored in a cache table but ultimately fetched from Active Directory. I manually created the join table - is that a problem? Anyway, so Event has a foreign key pointing to EventPracticeGroup, which has a foreign key pointing to PracticeGroupCache. PracticeGroupCache also has a RegionId pointing to the Regions table.
The problem comes when trying to insert a new EventPracticeGroup object. Below is the code I'm currently using:
var eventPracticeGroup = new EventPracticeGroup();
if (TryUpdateModel<EventPracticeGroup>(eventPracticeGroup))
{
/*
var eventId = EventScheduleRepository.GetById(Convert.ToInt32(Request.QueryString["EventScheduleId"])).EventId;
eventPracticeGroup.Event = EventRepository.GetById(eventId);
eventPracticeGroup.PracticeGroupCache = PracticeGroupCacheRepository.GetById(eventPracticeGroup.PracticeGroupCacheId);
eventPracticeGroup.PracticeGroupCache.Region = RegionRepository.GetById(eventPracticeGroup.PracticeGroupCache.RegionId);
EventPracticeGroupRepository.Add(eventPracticeGroup);
*/
var eventId = EventScheduleRepository.GetById(Convert.ToInt32(Request.QueryString["EventScheduleId"])).EventId;
var theEvent = new Event() { Id = eventId };
EventRepository.Repository.UnitOfWork.Context.AttachTo("Events",theEvent);
var practiceGroupCache = new PracticeGroupCache() { Id = eventPracticeGroup.PracticeGroupCacheId };
practiceGroupCache.Region = new Region() { Id = eventPracticeGroup.PracticeGroupCache.RegionId };
eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
EventPracticeGroupRepository.Add(eventPracticeGroup);
EventPracticeGroupRepository.Save();
return RedirectToAction("Index");
}
Anyway... as you can see, I've just tried using stub objects (no help), and I've also tried actually fetching and setting the objects. The error I get is:
Cannot insert the value NULL into column 'Name', table 'XXXX.dbo.Regions'; column does not allow nulls. INSERT fails. The statement has been terminated.
Obviously name is not a key field. I have checked the EDMX XML - only the Id (primary key columns) have StoreGeneratedPattern set to Identity, as they should (they are int32 identity columns). Not a single foreign key has StoreGeneratedPattern set to identity.
if I set Regions.Name to allow nulls, PracticeGroupCaches.Description throws the same error. It seems that every linked object gets set to null. I did have a look with the debugger, when I used the now commented out code, nothing was null and everything had a value. I even got the RegionRepository to return all of the regions, just to see if one of them somewhere had a null name. None did. There are only 2 in my test DB. Our object context is shared per HTTP request.
Please can anyone help. At this point I would settle for using the dirtiest workaround as long as it worked.
Regards,
Jonathan.
Look what happens when you call this line:
EventPracticeGroupRepository.Add(eventPracticeGroup);
You are adding a new eventPracticeGroup to the context. But eventPracticeGroup has the other related objects:
eventPracticeGroup -> PracticeGroupCache -> Region
And you create new objects for those:
var practiceGroupCache = new PracticeGroupCache() {
Id = eventPracticeGroup.PracticeGroupCacheId };
practiceGroupCache.Region = new Region() {
Id = eventPracticeGroup.PracticeGroupCache.RegionId };
eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
When you add the eventPracticeGroup to the context this whole object graph gets added which means that EF considers all three objects as new which have to be added to the DB. Since you only fill the Id properties other string properties (like Name or Description) are null. Because they are not nullable in the database the INSERT command fails.
But I guess that you don't want to insert the related entities into the DB anyway but only the eventPracticeGroup. So you need to attach them to the context before you add the new object, something like:
var practiceGroupCache = new PracticeGroupCache() {
Id = eventPracticeGroup.PracticeGroupCacheId };
EventRepository.Repository.UnitOfWork.Context.AttachTo(
"PracticeGroupCaches",practiceGroupCache);
practiceGroupCache.Region = new Region() {
Id = eventPracticeGroup.PracticeGroupCache.RegionId };
EventRepository.Repository.UnitOfWork.Context.AttachTo(
"Regions",practiceGroupCache.Region);
eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
EventPracticeGroupRepository.Add(eventPracticeGroup);
BTW as a side note: About this EventRepository.Repository.UnitOfWork.Context.XXX take a look at Ladislav Mrnka's answer here: EF 4.0 IsAttachedTo extension method and error An object with the same key already exists
Try to Add: [DatabaseGenerated(DatabaseGeneratedOption.None)]
On your Id field, Like:
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
It seems like you already found the problem and the solution. In your DB schema it seems like the columns don't allow NULL values. So either change all these columns to allow NULL or don't insert null (this is what you currently are trying to do)