EF6更新附加需求已修改,否则静默失败与EF4

克劳

您能告诉我为什么Entity Framework 6需要使用“ IsModified”代码行进行带有附件的更新,否则我的代码将为“ Silent Fail”,而不是Entity Framework 4?换句话说,在Entity Framework 4中,我进行了附有更新的工作。但是在EF6中,如果我做类似的事情,数据库将不会更新,也不会抛出异常(静默失败)。如果我在代码中放入“ IsModified”行,则可以正常工作,但这是不可接受的,因为开发人员可能会忽略“ IsModified”代码,并且更新将失败,并且没人知道。

在数据库中设置的以下条件下,此问题将在EF6中发生/不会发生:1.如果将active设置为默认值1并且AllowNulls = false,则更新失败2.如果未将active设置为默认值并且AllowNulls = false,则更新失败3.如果未将active设置为默认值并且AllowNulls = true,则更新有效。4.如果active设置为默认值1并且AllowNulls = true,则更新效果正常

这类似于:EntityFramework不保存null和false值,但不精确。我将引导您解决问题:

1)如果您拥有Visual Studio 2010,则可以继续进行,否则,您可以相信我EF4可以按照说明进行工作。

在Visual Studio 2010中,使用.NET Framework 4创建新项目ASP.NET MVC 2 Web应用程序,并将其命名为EF4Works。不要创建单元测试。

2)确保添加默认值并且不允许为空,这一点很重要

    CREATE TABLE [dbo].[Document](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [DocumentName] [varchar](10) NULL,
    [Active] [bit] NOT NULL CONSTRAINT [DF_Document_Active]  DEFAULT ((1)),
 CONSTRAINT [PK_Document] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

3)插入“ DocName”行1(true)

4)在此表中添加edmx。

5)在Home Index Controller中(如有必要,添加此控制器)添加并运行此代码(类似),并检查db IT WORKS!(updates db)(在调用视图之前插入断点):

    public ActionResult Index()
    {
        BreazEntities entities = new BreazEntities();
        Document document = new Document { Id = 1 };
        entities.Documents.Attach(document);
        document.Active = false;
        entities.SaveChanges();

        return View();
    }

6)将活动标志放回1

7)在Visual Studio 2013中添加新的解决方案和项目。Web,.NET Framework 4.5.1名为EF6Fails的ASP.NET WebApplication,下一个向导页面MVC,将身份验证更改为无身份验证。在程序包管理器控制台中:卸载程序包EntityFramework -project ef6fails -force,然后安装程序包EntityFramework -version 6.1.3 -project ef6fails

8)将ef6fails中的edmx添加到Document表中。

9)在控制器中运行以下代码,并在调用视图之前放置一个断点:

    public ActionResult Index()
    {
        BreazEntities6 entities = new BreazEntities6();
        Document document = new Document { Id = 1 };
        entities.Documents.Attach(document);
        document.Active = false;
        entities.SaveChanges();

        return View();
    }
  1. 这是行不通的。我将不得不执行以下操作,这是不可接受的,因为新开发人员可能会排除以下内容,并且不知道代码无法正常工作。有什么可以在解决方案中全局添加的,而不是让开发人员添加以下内容吗?我将进行研究并尝试自己添加一些东西,直到获得SO的答案:

        BreazEntities6 entities = new BreazEntities6();
        Document document = new Document { Id = 1 };
        entities.Documents.Attach(document);
        /*  The following line needs to be added in EF6, BUT not in EF4 */
        entities.Entry(document).Property(e => e.Active).IsModified = true;
        document.Active = false;
        entities.SaveChanges();
    
        return View();
    
格特·阿诺德

您要指出的是EF 4.1ObjectContext和EF 6(实际上是4.1和更高版本)之间在代码生成方面的区别DbContext

ObjectContextAPI中,一个数据库字段(如Active)将生成不少于此的代码:

/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Boolean Active
{
    get
    {
        return _Active;
    }
    set
    {
        OnActiveChanging(value);
        ReportPropertyChanging("Active");
        _Active = StructuralObject.SetValidValue(value);
        ReportPropertyChanged("Active");
        OnActiveChanged();
    }
}
private global::System.Boolean _Active;
partial void OnActiveChanging(global::System.Boolean value);
partial void OnActiveChanged();

这意味着,EF的更改跟踪器将立即被通知每个属性更改。

DbContextAPI不仅改变了对开发人员更友好的API,而且改变了更简单的类模型,并转向了真正的持久性无知。我相信,一开始仍然会生成自我跟踪代码,但最终,它会被放弃,而数据库字段将由一个简单的生成的自动属性来表示:

public bool Active { get; set; }

(毫无疑问,这样做也是为了在代码优先和数据库优先方法的基础上建立一个统一的代码库)。

不可避免地,这会使变更跟踪程序承担更多责任。它必须检测更改,而不是仅注册更改因此,更改跟踪器方法“随时”DetectChanges执行

回到您的代码。

在“旧” ObjectContextAPI中...

document.Active = false;

...将立即通知变更跟踪器该属性已设置。即使已经是错误的UPDATE也会发出SaveChanges

DbContextAPI中,更改跟踪器将永远不会将其检测为更改,因为Active已经具有booleans的默认值false没什么变化

简而言之,它曾经是“您设置的是您更新的内容”,后来变成了“您更改的是您更新的内容”。

很好,现在呢?

您可能想回到原来的状态。

那你呢

尝试稍微改变视角。假设您先进行代码工作,是否会像在第一个代码片段中那样编写属性代码?真的吗?首先,这是紧密耦合,没有单一责任。在断开连接的情况下(即重新连接反序列化的实体),可能会导致许多不必要的更新。

但是,即使您将编写(或生成)类似的代码,EF也不会监听更改。您必须自己在上下文中为物化实体预订一些变更传播代码。它不再是内置的,除非您返回到ObjectContextAPI(您不希望这样做)。

我会说:忍受它。您输了一些,但赢了很多(更多的SOLID代码)。习惯于控制数据库中的更新内容和未更新的内容您可能希望Active在实体的构造函数中将true设置为默认值,因此更改跟踪器会注意到对的更改false

但是我不认为开发人员会忘记它是一个有效的论点。开发人员应该具有灵活性。世界一直在变化,不能与时俱进。如果他们记得包括EF特定的语句Attach(管理实体状态),为什么不管理属性状态的语句呢?

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

从EF4升级后,在EF6中查询数据的空引用异常

来自分类Dev

实体框架急于在EF4和EF6中加载差异

来自分类Dev

更新EF4中的记录?

来自分类Dev

更新EF6时需要属性

来自分类Dev

EF6迁移(LocalDb)更新数据库登录失败

来自分类Dev

EF6代码优先:更新数据库登录失败

来自分类Dev

VS2013不允许我在不升级到EF5 / 6的情况下更新我的EF4模型

来自分类Dev

EF4:找不到AutoDetectChangesEnabled

来自分类Dev

EF4一对多映射

来自分类Dev

EF6操作已完成,因为已处置DbContext

来自分类Dev

使用EF6迁移失败重命名身份表

来自分类Dev

将EF 4添加/附加方法转换为EF 6

来自分类Dev

EF4更新导航属性IEntityChangeTracker的多个实例不能引用实体对象

来自分类Dev

EF4 RowCount 问题,而不是在更新其他表时插入触发器

来自分类Dev

如何使用EF6更新多对多表格

来自分类Dev

这是在EF6中更新对象的好方法

来自分类Dev

这是在EF6中更新对象的好方法

来自分类Dev

在EF6中更新实体会产生主键异常

来自分类Dev

在EF6中更新外键对象

来自分类Dev

更新 EF6 中的实体子集合

来自分类Dev

EF6嵌套交易

来自分类Dev

EF6应用代码

来自分类Dev

EF6 TPH与Oracle

来自分类Dev

带有EF6的IdentityServer4

来自分类Dev

来自表单的MVC4 EF6映射参数

来自分类Dev

编辑时如何验证EF4中的重复条目

来自分类Dev

获取EF4的运行时错误

来自分类Dev

对象关系(EF4)引起的Stackoverflow异常

来自分类Dev

编辑时如何验证EF4中的重复条目