c# - 更新 EF 中的实体属性,其中属性是另一个实体

标签 c# .net entity-framework

我正在使用 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 和 Updated 属性,但不适用于 Mime。我收到错误:

The property 'Mime' on type 'File' is not a primitive or complex property. The Property method can only be used with primitive or complex properties. Use the Reference or Collection method.

是否有可能实现这项工作并将其集成到我的存储库方法中?

最佳答案

是的,我认为这是可以做到的。这里的问题是,我没有看到任何简单的方法来检查属性是表格的一部分,还是导航属性。因此很难调用正确的行为。

如果您有兴趣,请查看 EF6 源代码,InternalEntityEntry.cs -> 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.

关于c# - 更新 EF 中的实体属性,其中属性是另一个实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26266652/

相关文章:

c# - 如何使用返回类型 ActionResult<T> 对操作进行单元测试?

c# - 泛型类与泛型方法

C# xamarin android 无法连接到任何指定的 MySQL 主机

.net - WCF ConcurrencyMode.Multiple连接最佳实践和缓存

linq - Entity Framework 链接 where 子句

C# ValueType equals 不比较属性?

初始化变量的 C# 命名约定 - 是否有特殊情况?

.net - Directory.GetFiles 返回重复的文件名

c# - 如何将用户/权限关系定义为 M :M?

entity-framework - Entity Framework + Java 脚本客户端