Entity framework 4 使用EF 4部分更新实体对象

Entity framework 4 使用EF 4部分更新实体对象,entity-framework-4,dto,object-graph,Entity Framework 4,Dto,Object Graph,我正在实现应用程序的DAL和BL层。 它作为WCF服务托管,EF4作为ORM使用。 我们有基于角色的安全层和业务规则,只有部分对象可以由特定角色更新 以下是问题的简化示例: 我们有这样的DTO: MainType { public Guid ID { get; set; } public String DoctorField1 { get; set; } public String DoctorField2 { get; set; } public String

我正在实现应用程序的DAL和BL层。 它作为WCF服务托管,EF4作为ORM使用。 我们有基于角色的安全层和业务规则,只有部分对象可以由特定角色更新

以下是问题的简化示例:

我们有这样的DTO:

MainType
{
    public Guid ID { get; set; }
    public String DoctorField1 { get; set; }
    public String DoctorField2 { get; set; }
    public String NurseField1 { get; set; }
    public String NurseField2 { get; set; }
    public DateTime Created {get; set;}
    public DateTime Updated {get; set;}
    public Guid LastUpdateBy {get; set;}

    public List<DetailsType> Details { get; set; }
}

DetailsType
{
    public Guid MainTypeID { get; set; }
    public Guid SomeIdentityID { get; set; }

    public String DoctorDetail { get; set; }
    public String NurseDetail { get; set; }
    public DateTime Created {get; set;}
    public DateTime Updated {get; set;}
    public Guid LastUpdateBy {get; set;}
}
main类型
{
公共Guid ID{get;set;}
公共字符串DoctorField1{get;set;}
公共字符串DoctorField2{get;set;}
公共字符串NurseField1{get;set;}
公共字符串NurseField2{get;set;}
已创建公共日期时间{get;set;}
公共日期时间已更新{get;set;}
公共Guid LastUpdateBy{get;set;}
公共列表详细信息{get;set;}
}
细节类型
{
公共Guid MainTypeID{get;set;}
公共Guid SomeIdentityID{get;set;}
公共字符串DoctorDetail{get;set;}
公共字符串NurseDetail{get;set;}
已创建公共日期时间{get;set;}
公共日期时间已更新{get;set;}
公共Guid LastUpdateBy{get;set;}
}
这些实体映射到具有相同字段的对应DB表

  • MainType的ID字段为主键
  • DetailsType的MainTypeID是MainType表的外键
  • DetailsType的SomeIdentityID是FK,与其他对此示例不重要的实体相关联
  • MainTypeID SomeIdentityID是DetailsType表的复杂主键
我有这类对象的图表(1个主要和列表细节),并确定了执行更新操作的用户的角色。 我的任务是:

  • 如果当前用户在主对象和所有详细信息对象中具有角色医生-更新医生字段,请插入新的详细信息对象
  • 如果当前用户在主对象和所有详细信息对象中具有角色护士-更新护士字段
  • 将当前日期保存到更新字段
  • 将当前用户id保存到LastUpdateBy字段
  • 不要修改已创建的字段和未由此角色更新的任何其他字段
例如,如果我有一个角色为医生的用户,我应该执行以下操作:

  • 在MainObject中更新DoctorField1、DoctorField2、Updated、LastUpdateBy
  • 在每个详细信息对象中更新DoctorDetail、Updated、LastUpdateBy
  • 不要修改任何其他字段
目前,我们有一个实现,可以读取MainObject的完整图形,进行必要的修改并保存回DB。 这个解决方案太慢了,我需要找到一种改进的方法。 目前,我清楚地知道如何通过原始SQL实现这一点,但这将是我的解决方案,以防没有其他任何帮助

如何使实体框架只更新所需的字段而忽略另一个字段

我对字符串字段的ApplyOriginalValues和ApplyCurrentValues方法取得了一些成功的结果。 想法是为这两个对象中的属性指定一些虚拟值,例如字符串“@$%&@$%&@$%&@$%&@$%&@$$%&@$$%&@$$%&@$$%&”,然后EF在保存更改时将它们视为未修改的属性。 但是,此技巧不适用于布尔值、Int32和十进制值。 我应该对所有对象使用一些简单的方法


我将非常感谢您对这个问题的任何想法和想法。

如果您有这样的具体要求,您应该首先修改您的WCF服务,以不接受用户无法修改的字段。这导致了两个简单的DTO:

public class MainTypeUpdateDto
{    
    public Guid ID { get; set; }
    public String Field1 { get; set; }
    public String Field2 { get; set; }
    public List<DetailsTypeUpdateDto> Details { get; set; }
}

public class DetailsTypeUpdateDto
{
    public Guid MainTypeID { get; set; }
    public Guid SomeIdentityID { get; set; }
    public String Detail { get; set; }
}
public类main类型更新为
{    
公共Guid ID{get;set;}
公共字符串字段1{get;set;}
公共字符串字段2{get;set;}
公共列表详细信息{get;set;}
}
公共类详细信息已更新为
{
公共Guid MainTypeID{get;set;}
公共Guid SomeIdentityID{get;set;}
公共字符串详细信息{get;set;}
}
所有其他字段要么无法更新,要么应由服务器端逻辑处理

现在,当您收到DTO时,您可以将它们映射回真实的实体对象。根据用户角色,您将知道必须设置哪些字段和详细信息。有两个选项可强制EF仅保存所需的字段:

  • 首先使用
    main类型
    和相关详细信息创建对象图。仅在这些实体中设置ID,并将
    MainType
    实体附加到上下文。之后,将所有可更新字段设置为当前值。不要更改任何实体的状态
  • 使用
    MainType和所有相关详细信息创建对象图,并设置所有ID和所有可更新字段。之后,将
    MainType`实体附加到上下文和每个修改的属性(在每个实体上)

如果用户还可以删除或添加详细信息,您可能需要一些附加逻辑。

谢谢您的回答,但现在更改DTO为时已晚。还有一件事是护士不允许编辑医生的字段,但她仍然需要在UI上看到它们,因此它们应该存在于DTO对象中,但不会映射回。您的手动设置属性状态的解决方案在布尔和字符串属性上非常有效,完全解决了我的部分更新问题,但是,它不适用于外键属性。例如,如果我在细节中有一些值,实际上是其他表中的FK值。