我正在使用Entity Framework 6,我需要更新实体的属性。
我有以下实体:
public class File
{
public Int32 Id { get; set; }
public Byte Data { get; set; }
public DateTime Updated { get; set; }
public virtual Mime Mime { get; set; }
}
public class Mime
{
public Int32 Id { get; set; }
public String Name { get; set; }
public virtual ICollection<File> Files { get; set; }
}
然后我使用了以下内容:
_repository.Update<File>(file, x => x.Data, x => x.Mime, x => x.Updated);
存储库方法如下:
public void Update<T>(T entity,
params Expression<Func<T, Object>>[] properties)
where T : class
{
_context.Set<T>().Attach(entity);
foreach (var property in properties)
{
MemberExpression expression =
property.Body is MemberExpression ?
(MemberExpression)property.Body :
(MemberExpression)(((UnaryExpression)property.Body)
.Operand);
_context.Entry<T>(entity)
.Property(expression.Member.Name).IsModified = true;
}
}
这适用于Data
和更新的属性,但不适用于Mime
。我收到错误:
“File”类型的属性“Mime”不是原始属性或复杂属性。 Property方法只能与原始或复杂属性一起使用。使用Reference或Collection方法。
是否可以将其工作并将其集成到我的存储库方法中?
答案 0 :(得分:0)
是的,我认为可以做到。这里的问题是,我没有看到任何简单的方法来检查只要属性是表的一部分,或者是导航属性。因此很难调用正确的行为。
如果您有兴趣,请查看EF6源代码,InternalEntityEntry.cs
- &gt; Property(..)
通过元数据进行大量的属性验证。
主要思想是基本扫描您的概念模型,并确定属性何时是导航属性(例如,如果属性导向另一个表),或者它是否复杂/原始。
据此,你称之为正确的功能。
var propertyName = expression.Member.Name;
var propertyType = __get_property_type__(propertyName);
if(propertyType==Property || propertyType==Complex)
{
_context.Entry<T>(entity)
.Property(propertyName).IsModified = true;
continue;
}
if(propertyType==Navigational){
// hm, do we need Attach it first?!
// not sure.. have to test first.
dynamic underlyingReference = entity.GetType()
.GetProperty(propertyName)
.GetValue(entity, null);
_context.Entry(underlyingReference).State = EntityState.Modified;
}
这里的问题是让__get_property_type__
有效。有Microsoft.Data.Edm.dll让你使用概念模型,但我认为这并不容易。
这是EF6如何检测我们是否处理引用属性的方式:
EdmMember member;
EdmEntityType.Members.TryGetValue(propertyName, false, out member);
var asNavProperty = member as NavigationProperty;
// if asNavProperty!=null, we have navigation property.
答案 1 :(得分:-2)
100%Gerts指向。我认为没有理由以他们的方式解决问题。 无论如何,要回答这个问题。你有另一个答案。可能有用。
缺少的是:
如何从上下文中获取托管类型列表。
public static IList<Type> GetContextManagedTypes(DbContext context) {
ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext;
MetadataWorkspace workspace = objContext.MetadataWorkspace;
IEnumerable<EntityType> managedTypes = workspace.GetItems<EntityType>(DataSpace.OSpace);
var typeList = new List<Type>();
foreach (var managedType in managedTypes) {
var pocoType = managedType.FullName.GetCoreType();
typeList.Add(pocoType);
}
return typeList;
}