[ACCEPTED]-Setting a foreign key to null when using entity framework code first-entity-framework-4.1
I think the problem is that as far as the 12 context is concerned, you haven't actually changed anything.
You can use the lazy 11 loading approach previously suggested by 10 using virtual
, but since you haven't requested 9 that the Employee be loaded yet, it's still 8 null. You could try this:
var forceLoad = project.Employee;
project.Employee = null; // Now EF knows something has changed
Context.SaveChanges();
Alternatively, explicitly 7 include it in your original request:
var project = Context.Projects.Include(x => x.Employee).FirstOrDefault(x => x.ProjectId == projectId);
project.Employee = null;
Context.SaveChanges();
On a 6 side note, FirstOrDefault
will return null
if no Project
matches 5 the given id. If you know the project exists, you 4 can just use First
. You could even use Single
which 3 will assert that there is only one such 2 project. If you continue to use FirstOrDefault
, I'd recommend 1 checking for null
before working with project
.
You can do it this way, which means you 1 don't have to load the related entity.
context.Entry(Project).Reference(r => r.Employee).CurrentValue = null;
The answer to this is quite simple. EF can't 3 infer the type given the information you've 2 provided.
Just do this instead:
public void RemoveEmployeeFromProject(int projectId)
{
var project = Context.Projects.FirstOrDefault(x => x.ProjectId == projectId);
project.EmployeeId = (int?)null;
Context.SaveChanges();
}
and it will 1 work.
if you enable lazy loading by making the 5 employee property virtual does it work?
public class Project
{
public int ProjectId {get; set;}
public virtual Employee Employee {get;set;}
}
i'd 4 also suggest encapsulating the remove method 3 as part of your poco class to making the 2 meaning more clear. see this article for more 1 details on that.
public class Project
{
public int ProjectId {get; set;}
public virtual Employee Employee {get;set;}
public void RemoveEmployee()
{
Employee = null;
}
}
You need to include in the linq query, the 2 property to assign, using the same name 1 it has in the Project class:
var project = Context.Projects.Include("Employee").FirstOrDefault(x => x.ProjectId == projectId);
As another workaround, I compiled two methods 6 into a extension method:
public static void SetToNull<TEntity, TProperty>(this TEntity entity, Expression<Func<TEntity, TProperty>> navigationProperty, DbContext context = null)
where TEntity : class
where TProperty : class
{
var pi = GetPropertyInfo(entity, navigationProperty);
if (context != null)
{
//If DB Context is supplied, use Entry/Reference method to null out current value
context.Entry(entity).Reference(navigationProperty).CurrentValue = null;
}
else
{
//If no DB Context, then lazy load first
var prevValue = (TProperty)pi.GetValue(entity);
}
pi.SetValue(entity, null);
}
static PropertyInfo GetPropertyInfo<TSource, TProperty>( TSource source, Expression<Func<TSource, TProperty>> propertyLambda)
{
Type type = typeof(TSource);
MemberExpression member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
propertyLambda.ToString()));
PropertyInfo propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
propertyLambda.ToString()));
if (type != propInfo.ReflectedType &&
!type.IsSubclassOf(propInfo.ReflectedType))
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a property that is not from type {1}.",
propertyLambda.ToString(),
type));
return propInfo;
}
This allows you 5 to supply a DbContext if you have one, in 4 which case it will use the most efficient 3 method and set the CurrentValue of the Entry 2 Reference to null.
entity.SetToNull(e => e.ReferenceProperty, dbContext);
If no DBContext is supplied, it 1 will lazy load first.
entity.SetToNull(e => e.ReferenceProperty);
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.