为什么EF Core Update无法更新已修改的列

时间:2017-02-21 21:17:22

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

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

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

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

当我使用Update命令更新任何这些列的值时...它完全正常...除了一列。当我尝试更新那一列并处理更新时,它将保存所有更改......但是该列只是将其恢复为之前的值。

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

下面是实体的上下文条目....有问题的列是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);

下面是一些图像,显示了数据库中列的外键约束和列属性的配置。

enter image description here enter image description here

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

UPDATE :::

我创建了复制数据库结构并生成测试数据的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

1 个答案:

答案 0 :(得分:0)

看起来我想通了。

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

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

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

所以基本上如果你要对一个包含导航属性的实体进行更新,那么约束列就是..你要么也要更新那个属性..否则从更新后的属性中删除引用