【问题标题】:Why is EF Core Update failing to update a modified column为什么 EF Core Update 无法更新已修改的列
【发布时间】:2017-07-11 17:10:09
【问题描述】:

我正在使用 EF Core 并尝试更新实体的列/属性。

该列有一个外键约束...可以为空并且是一个 int。

同一个表/实体有三个或四个其他列/属性相同的数据类型也有外键约束......并且可以为空

当我使用更新命令更新任何这些列的值时...它工作得非常好...除了一列。当我尝试更新该列并处理更新时,它将保存所有更改...但该列只是将其恢复为以前的值。

它不会抛出异常......没有任何类型的错误......只是将其恢复为原始值并继续。

以下是实体的上下文条目....有问题的列是 car_app_id

上下文文件中没有任何内容可以将该特定列与其他列区分开来...外键约束中没有任何内容与其他列不同...

            {
            entity.HasKey(e => e.AppId)
                .HasName("PK_tbl_apps");

    entity.ToTable("tbl_apps");

            entity.Property(e => e.AppId).HasColumnName("app_id");

    entity.Property(e => e.Active).HasColumnName("active");

    entity.Property(e => e.AppAcro)
                .HasColumnName("app_acro")
                .HasColumnType("varchar(50)");

    entity.Property(e => e.AppDesc)
                .HasColumnName("app_desc")
                .HasColumnType("varchar(5000)");

    entity.Property(e => e.AppTypeId).HasColumnName("app_type_id");

    entity.Property(e => e.BuildTypeId).HasColumnName("build_type_id");

    entity.Property(e => e.CarAppId).HasColumnName("car_app_id");       

    entity.Property(e => e.ControlLevelId).HasColumnName("control_level_id");     

    entity.Property(e => e.Deleted).HasColumnName("deleted");

    entity.HasOne(d => d.AppType)
                .WithMany(p => p.TblApps)
                .HasForeignKey(d => d.AppTypeId)
                .HasConstraintName("FK_tbl_apps_tbl_app_types");

    entity.HasOne(d => d.BuildType)
                .WithMany(p => p.TblApps)
                .HasForeignKey(d => d.BuildTypeId)
                .HasConstraintName("FK_tbl_apps_tbl_build_types");

    entity.HasOne(d => d.CarApp)
                .WithMany(p => p.TblApps)
                .HasForeignKey(d => d.CarAppId)
                .HasConstraintName("FK_tbl_apps_tbl_car_apps");

    entity.HasOne(d => d.ControlLevel)
                .WithMany(p => p.TblApps)
                .HasForeignKey(d => d.ControlLevelId)
                .HasConstraintName("FK_tbl_apps_tbl_control_level");


});

这是我用来测试的代码。这是简单的测试代码,试图找出更新不起作用的原因。它非常基本的存储库

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        private omni_dbContext context { get; set; }
        private DbSet<TEntity> dbset { get; set; }
        public Repository()
        {
            try
            {
                context = new omni_dbContext();
                dbset = context.Set<TEntity>();

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { }
        }
        public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
           params Expression<Func<TEntity, object>>[] includeProperties)
        {
            try
            {
                IQueryable<TEntity> query = dbset;
                if (filter != null)
                {
                    query = query.Where(filter);
                }
                if (includeProperties != null)
                {
                    foreach (var includeProperty in includeProperties)
                    {
                        query = query.Include(includeProperty);
                    }
                }
                return query.ToList();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { }
        }



        public void Update(TEntity entity)
        {
            try
            {
                context.Update(entity);
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally { }
        }


    }
}

所以我为实体使用了一个 Manager 类来实例化存储库并进行数据调用。

基本上我得到一组记录..挑选一个记录...更新属性并将其发送回更新,每个字段都会更新得很好..但是实体将 car_app_id 属性重置为之前的任何内容我修改它,我不明白为什么。

 EalmsEF.AppManager manager = new EalmsEF.AppManager();
                var apps = manager.GetActiveFull().Where(a => a.CarAppId != null).ToList();
                var app = apps[0];
                app.CarAppId = 2;
                app.BuildTypeId = 2;
                manager.Update(app);

下面是几张图片,显示了数据库中对列的外键约束的配置以及列的属性。

如果有人知道为什么这一列会拒绝正确更新,那将是一个很大的帮助。

更新:::

我创建了复制数据库结构并生成测试数据的 sql 脚本。基本上你创建了一个名为 test..runt 的数据库,这两个脚本创建了这个重复的数据库,这个问题可以被复制。

    USE [test]
GO

/****** Object:  Table [dbo].[tbl_control_level]    Script Date: 2/21/2017 3:30:29 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_control_level](
    [control_level_id] [int] IDENTITY(1,1) NOT NULL,
    [control_level] [varchar](50) NULL,
    [description] [varchar](1000) NULL,
    [deleted] [bit] NULL,

 CONSTRAINT [PK_tbl_control_level] PRIMARY KEY CLUSTERED 
(
    [control_level_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO



/****** Object:  Table [dbo].[tbl_app_types]    Script Date: 2/21/2017 3:29:51 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_app_types](
    [app_type_id] [int] IDENTITY(1,1) NOT NULL,
    [app_type] [varchar](50) NULL,
    [deleted] [bit] NULL,   
 CONSTRAINT [PK_tbl_app_types] PRIMARY KEY CLUSTERED 
(
    [app_type_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO


/****** Object:  Table [dbo].[tbl_car_apps]    Script Date: 2/21/2017 3:31:32 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_car_apps](
    [car_app_id] [int] IDENTITY(1,1) NOT NULL,
    [car_id] [varchar](50) NULL,    
    [deleted] [bit] NULL,
     CONSTRAINT [PK_tbl_car_apps] PRIMARY KEY CLUSTERED 
(
    [car_app_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO



/****** Object:  Table [dbo].[tbl_control_level]    Script Date: 2/21/2017 3:30:29 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_control_level](
    [control_level_id] [int] IDENTITY(1,1) NOT NULL,
    [control_level] [varchar](50) NULL,
    [description] [varchar](1000) NULL,
    [deleted] [bit] NULL,

 CONSTRAINT [PK_tbl_control_level] PRIMARY KEY CLUSTERED 
(
    [control_level_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO




/****** Object:  Table [dbo].[tbl_build_types]    Script Date: 2/21/2017 3:29:15 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_build_types](
    [build_type_id] [int] IDENTITY(1,1) NOT NULL,
    [build_type] [varchar](50) NULL,
    [deleted] [bit] NULL,
 CONSTRAINT [PK_tbl_build_types] PRIMARY KEY CLUSTERED 
(
    [build_type_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO


/****** Object:  Table [dbo].[tbl_apps]    Script Date: 2/21/2017 3:25:58 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbl_apps](
    [app_id] [int] IDENTITY(1,1) NOT NULL,
    [app_acro] [varchar](50) NULL,
    [app_name] [varchar](100) NULL, 
    [app_type_id] [int] NULL,   
    [control_level_id] [int] NULL,
    [build_type_id] [int] NULL, 
    [car_app_id] [int] NULL,
    [deleted] [bit] NULL,

 CONSTRAINT [PK_tbl_apps] PRIMARY KEY CLUSTERED 
(
    [app_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[tbl_apps]  WITH CHECK ADD  CONSTRAINT [FK_tbl_apps_tbl_app_types] FOREIGN KEY([app_type_id])
REFERENCES [dbo].[tbl_app_types] ([app_type_id])
GO

ALTER TABLE [dbo].[tbl_apps] CHECK CONSTRAINT [FK_tbl_apps_tbl_app_types]
GO

ALTER TABLE [dbo].[tbl_apps]  WITH CHECK ADD  CONSTRAINT [FK_tbl_apps_tbl_build_types] FOREIGN KEY([build_type_id])
REFERENCES [dbo].[tbl_build_types] ([build_type_id])
GO

ALTER TABLE [dbo].[tbl_apps] CHECK CONSTRAINT [FK_tbl_apps_tbl_build_types]
GO

ALTER TABLE [dbo].[tbl_apps]  WITH CHECK ADD  CONSTRAINT [FK_tbl_apps_tbl_car_apps] FOREIGN KEY([car_app_id])
REFERENCES [dbo].[tbl_car_apps] ([car_app_id])
GO

ALTER TABLE [dbo].[tbl_apps] CHECK CONSTRAINT [FK_tbl_apps_tbl_car_apps]
GO

ALTER TABLE [dbo].[tbl_apps]  WITH CHECK ADD  CONSTRAINT [FK_tbl_apps_tbl_control_level] FOREIGN KEY([control_level_id])
REFERENCES [dbo].[tbl_control_level] ([control_level_id])
GO

ALTER TABLE [dbo].[tbl_apps] CHECK CONSTRAINT [FK_tbl_apps_tbl_control_level]
GO




     USE [test]
GO

INSERT INTO [dbo].[tbl_app_types]
           ([app_type]
           ,[deleted])
     VALUES
           ('app type 1'
           ,0)
GO

INSERT INTO [dbo].[tbl_app_types]
           ([app_type]
           ,[deleted])
     VALUES
           ('app type 2'
           ,0)
GO


INSERT INTO [dbo].[tbl_build_types]
           ([build_type]
           ,[deleted])
     VALUES
           ('build type 1'
           ,0)
GO

INSERT INTO [dbo].[tbl_build_types]
           ([build_type]
           ,[deleted])
     VALUES
           ('build type 2'
           ,0)
GO

INSERT INTO [dbo].[tbl_control_level]
           ([control_level]
           ,[description]
           ,[deleted])
     VALUES
           ('ct 1'
           ,''
           ,0)
GO

INSERT INTO [dbo].[tbl_control_level]
           ([control_level]
           ,[description]
           ,[deleted])
     VALUES
           ('ct 2'
           ,''
           ,0)
GO

INSERT INTO [dbo].[tbl_car_apps]
           ([car_id]
           ,[deleted])
     VALUES
           ('1'
           ,0)
GO

INSERT INTO [dbo].[tbl_car_apps]
           ([car_id]
           ,[deleted])
     VALUES
           ('2'
           ,0)
GO

INSERT INTO [dbo].[tbl_apps]
           ([app_acro]
           ,[app_name]
           ,[app_type_id]
           ,[control_level_id]
           ,[build_type_id]
           ,[car_app_id]
           ,[deleted])
     VALUES
           ('testapp1'
           ,''
           ,1
           ,1
           ,1
           ,1
           ,0)
GO

INSERT INTO [dbo].[tbl_apps]
           ([app_acro]
           ,[app_name]
           ,[app_type_id]
           ,[control_level_id]
           ,[build_type_id]
           ,[car_app_id]
           ,[deleted])
     VALUES
           ('testapp2'
           ,''
           ,1
           ,1
           ,1
           ,1
           ,0)
GO

【问题讨论】:

  • 更新外键值后是否加载更多数据?
  • 关系走向何方?更新汽车表中的键不会破坏与其他表的关系吗?
  • 我没有进一步更新或加载数据。它的一个简单的获取记录修改属性和更新实体。至于更新密钥..我没有更新 car 表中的密钥..我将 app 表中的引用列更新为 car 表中不同的可行记录。
  • 如上所述...我可以更新此实体上的任何列/属性。只是不是 car_app_id 值。为什么我可以更新内置类型 ID 或应用类型 ID 就好了..但是当我尝试更新 car_app_id 时。它只是恢复该值并继续前进......该列不会更新的内容是什么。该值是有效的......它是一个有效的记录,因此它不会违反约束......并且管理器中的所有更新方法都是实例化存储库并将存储库调用到 TblApps 对象并调用更新方法。跨度>

标签: c# entity-framework asp.net-core


【解决方案1】:

看来我想通了。

经过进一步调查,这就是我发现的......

正在更新的实体是通过包含在导航对象中获取的。所以这个特定的实例..CarApp 对象包含在记录的“获取”中。由于某种原因,这导致更新将更改重置为导航属性中设置的值。

出于好奇,我在 get 中添加了其他属性作为包含,并且它开始对它们进行相同的行为...当我删除导航属性的所有包含并尝试保存更新时它工作正常。

因此,基本上,如果您要对包含导航属性的实体进行更新,则受限列适用于..您要么也必须更新该属性..或者从更新的属性中删除引用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-08
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多