0

我已经开始为 MVC n 层应用程序使用实体框架 (EF)。很明显,这是一个 Web 应用程序(它是无状态的),我将不得不使用分离的对象模型。执行 Add 操作没有歧义。但是,在进行编辑时,有两种方法

  1. 在上下文中获取原始对象,附加更新的对象,然后保存到数据库。在回答这个问题 EF4 Context.ApplyCurrentValues 时提到的东西 不会更新当前值
  2. 使用本文中提到的对象的各个字段的 IsModified 属性显式设置各个修改的属性 http://msdn.microsoft.com/en-us/data/jj592677.aspx

方法 1 的缺点是每次需要执行更新时都必须将对象从数据库加载到内存中。方法 2 将需要从要更新对象的任何位置手动传递要设置为 IsModified 的字段为 true。因此,例如对于每个对象,我可能需要为对象的每个字段创建一个布尔集合对象。例如

SaveEntity(EntityClass e, EntityStateClass ec)
{
  context.Entry(e).Property("Name").IsModified = ec.NameState;

  context.SaveChanges();
}

class EntityStateClass{ public bool NameState;} 

出于性能考虑,我更喜欢方法 2,但我受到我正在使用的 n 层架构和存储库模式的阻碍。我的存储库接口限制任何对象的保存方法

 SaveEntity(EntityClass e);

所以我不能传递“状态”对象。上下文类不可用,不应该在 DAL 之外可用。所以我不能在外面设置属性。有没有“正确”的方法来实现这一目标?
注意:自我跟踪实体也没有问题,因为我无法将具有状态的实体发送到客户端(浏览器),因为我打算保持 html 轻量级。

编辑:经过深思熟虑,我试图使用以下机制来跟踪我的域类中每个字段的修改状态

  • 为实体类声明一个部分类。
  • 对于每个可更新的字段,声明一个布尔属性,如“ IsModified_FieldName
  • 设置字段时设置“IsModified_FieldName ”属性。

但是为此,我需要 Entity Framework 为我生成显式属性,而不是它自动生成的隐式属性。EF 是否提供了执行此操作的句柄?

这是我想要实现的示例代码

 //Save Method for class EntityClass. 
 SaveEntity(EntityClass e)
 {
   context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
   context.SaveChanges();
 }

//EntityClass is class autogenerated by EF
 public partial class EntityClass
  {

        //This is auto-generated property by EF
        public string Name {get; set;}

        /* This is what I would like EF to do
            private string name;
            public string Name 
            {
               get {return Name;}
               set {
                     name = value;
                     //this is what I would like to do
                     this.IsModified_Name = true;
                   };

            }
         */
 }

 //This is another partial definition for EntityClass that I will provide
  public partial class EntityClass
  {
     //This property will be set to true if "Name" is set
      public bool IsModified_Name {get; set;}
  }

PS:看来我提供的信息不充分,所以没有回复。

  • 我正在使用 DbContext(数据库优先模型)
  • EF 为我自动生成类文件。所以每次我更新我的数据库时,都会重新生成类文件。
4

1 回答 1

1

对于您的具体问题:实体是由 T4 模板生成的,应该可以修改此模板(文本格式)以您想要塑造实体的方式生成实体。

但我对你的概念有几点意见:

  • 在 Web 应用程序中,数据通常由用户在浏览器中更改。要确定真正发生了哪些更改,您需要跟踪浏览器中的更改(可能是通过一些 Javascript 在用户编辑文本框时在数据中设置标志(例如 ViewModel))。

    如果您不跟踪浏览器中的更改,会发生什么?数据被发送回服务器,而您在服务器端(使用控制器中的 MVC)不知道哪个属性已更改。因此,您唯一的机会是将所有已发布回您的属性映射,EntityClass并且每个属性都将标记为Modified,无论用户是否真的进行了更改。当您稍后调用SaveChangesEF 时,将编写一个UPDATE涉及所有这些属性的语句,并且您需要避免不必要的开销。

  • 那么,通过设置单个属性而不是将整个实体的状态设置为 ,您获得了什么Modified在这两种情况下,您都将所有属性标记为Modified。例外是实体的部分更改,例如:您有一个Customer实体,该实体具有一个NameandCity属性和一个仅允许编辑Name但不允许编辑的视图,City以及一个仅包含一个Name属性的相应 ViewModel。在这种情况下,您的程序只会将实体的Name属性标记为而不是. 您可能会在此处保存一点,因为您没有将属性值保存到数据库中。但是即使它没有更改,您仍然可以保存。CustomerModifiedCityCityName

  • 如果您使用解决方案 1 ( ApplyCurrentValues),您必须首先从数据库中加载实体,是的,但它只会将属性标记为Modified与数据库中的值相比确实发生了变化。如果用户没有更改任何内容,则根本UPDATE不会写入任何内容。

  • 请记住,您只是在开始实施您的概念。除了标量属性更改(即关系更改)之外,浏览器中还可能发生其他数据更改。例如,用户将关系从 an 更改Order为 a Customer,或者您有一个包含 anOrder和集合的视图,OrderItems并且用户不仅可以编辑Order标题,还可以编辑OrderItems 并删除和添加新OrderItem的 s。当数据从浏览器返回到服务器时,您希望如何识别哪些集合项已添加,哪些已删除 - 除非您在浏览器中跟踪所有这些更改并将跟踪信息发送回服务器实际数据或除非您重新加载OrderOrderItems 并将更改合并到数据库中的原始实体中?

出于以下原因,我个人会投票支持选项 1:

  • 您可以使用不携带额外跟踪信息的真实 POCO。(顺便说一句:我怀疑您是否没有通过实施自己的 EF 更改跟踪代理开箱即用的跟踪来重新发明轮子。)

  • 您不需要跟踪浏览器中的更改,这可能会变得非常复杂,并且需要在每个编辑视图中使用 Javascript 将更改标志写入隐藏的表单字段或其他内容。

  • 您可以使用 EF 的标准功能,而无需实现自己的跟踪。

  • 当您想要更新实体时,您需要从数据库中加载实体,这是真的。但这是否是 Web 应用程序中真正的性能瓶颈,其中数据必须通过网络来回运行(并且模型绑定器涉及反射(实际上并不是很快))?如果您的数据库远离 Web 服务器并通过 9600 波特调制解调器连接,我无话可说。但除此之外,您的计划不仅是过早的优化,而且是一种过早的架构。您开始基于“它可能很慢”来构建一个潜在的复杂架构,以解决您实际上不知道它是否真的存在的性能问题。

于 2013-02-02T14:35:23.730 回答