0

我正在实现应用程序的 DAL 和 BL 层。它作为 WCF 服务托管,EF 4 用作 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;}
}

这些实体映射到具有相同字段的相应数据库表。

  • MainType 的 ID 字段是 Primary Key;
  • DetailsType 的 MainTypeID 是 MainType 表的外键。
  • DetailsType 的 SomeIdentityID 是对本示例不重要的某个其他实体的 FK。
  • MainTypeID SomeIdentityID 是 DetailsType 表的复杂主键。

我有此类对象的图表(1 个主要和列表详细信息),并确定了执行更新操作的用户的角色。我的任务是:

  • 如果当前用户具有角色 Doctor - 更新 Main 对象和所有 Details 对象中的 Doctor 字段,插入新的详细信息对象。
  • 如果当前用户具有护士角色 - 更新 Main 对象和所有 Details 对象中的 Nurse 字段。
  • 将当前日期保存到更新字段
  • 将当前用户 ID 保存到 LastUpdateBy 字段
  • 不要修改 Created 字段和任何其他未由该角色更新的字段。

因此,例如,如果我有角色为 Doctor 的用户,我应该执行以下操作:

  • 更新 MainObject 中的 DoctorField1、DoctorField2、Updated、LastUpdateBy
  • 在每个详细信息对象中更新 DoctorDetail、Updated、LastUpdateBy
  • 不要修改任何其他字段。

目前我们有实现读取 MainObject 的完整图形,进行必要的修改并保存回 DB。该解决方案运行速度太慢,我需要找到改进它的方法。目前我清楚地知道如何通过 RAW SQL 来做到这一点,但这将是我的解决方案,以防万一没有其他帮助。

我怎样才能让实体框架只更新需要的字段而忽略另一个。

对于字符串字段,我使用 ApplyOriginalValues 和 ApplyCurrentValues 方法获得了一些成功的结果。想法是为两个对象中的属性分配一些虚构的值,例如字符串“@#$%&@#$%&@#$%&@#$%&@#$%&”,然后 EF 将它们视为保存更改期间未修改属性。但是,此技巧不适用于 Boolean、Int32 和 Decimal 值。我应该对所有对象使用一些简单的方法。

我将不胜感激有关此问题的任何想法和想法。

4

1 回答 1

1

如果您有这样的特定要求,您应该首先修改您的 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; }
}

所有其他字段要么无法更新,要么应由您的服务器端逻辑处理。

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

  • 首先创建具有MainType相关详细信息的对象图。仅在这些实体中设置 Id 并将MainType实体附加到上下文。之后将所有可更新字段设置为当前值。不要改变任何实体的状态。
  • MainType and all related details and set all Ids and all updatable fields. After that attach使用MainType 实体创建对象图到上下文,并为每个修改的属性(在每个实体上)手动设置状态。

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

于 2011-12-04T15:39:27.633 回答