Entity Framework пишет в контексте, но не в базе данных

Мы используем подход UnitOfWork для приложения, основанного на EF 6.2.0 в C# с бэкэндом базы данных SQL Server 2017 Express (14.0.1000).

наш OwnContext.cs унаследованный от DbContext следует заполнить поля Id, ChangedDate а также ChangedUser автоматически, который является частью каждой сущности в нашей модели БД:

public partial class OwnContext : DbContext {

    public override int SaveChanges()
    {
        bool hasChanges = false;

        this.ChangeTracker.DetectChanges();

        #region Fill Created, Changed

        foreach (var item in this.ChangeTracker.Entries()
            .Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted)))
        {
            if (item.State == EntityState.Deleted)
            {
                hasChanges = true;
            }
            else
            {
                // Id
                PropertyInfo pI = item.Entity.GetType().GetProperty("Id");
                if (pI != null)
                {
                    Guid id = (Guid)pI.GetValue(item.Entity, null);
                    if ((Guid)id == Guid.Empty)
                    {
                        id = Guid.NewGuid();
                        pI.SetValue(item.Entity, id);
                    }
                }

                DateTime now = DateTime.Now;

                // Timestamp & User
                pI = item.Entity.GetType().GetProperty("CreatedDate");
                if (pI != null)
                {
                    var date = pI.GetValue(item.Entity, null);
                    // Only if empty on new records
                    if (date == null || date.Equals(DateTime.MinValue))
                    {
                        pI.SetValue(item.Entity, now);
                        pI = item.Entity.GetType().GetProperty("CreatedUser");
                        if (pI != null)
                        {
                            pI.SetValue(item.Entity, Environment.UserName); 
                        }
                    }
                    pI = item.Entity.GetType().GetProperty("ChangedDate");
                    if (pI != null)
                    {
                        pI.SetValue(item.Entity, now);
                    }
                    pI = item.Entity.GetType().GetProperty("ChangedUser");
                    if (pI != null)
                    {
                        pI.SetValue(item.Entity, Environment.UserName); 
                    }
                }

                hasChanges = true;

            }

        }

        #endregion

        int countChanges = 0;

        if (hasChanges)
        {
            // Call SaveChanges Method from Context;
            try
            {
                countChanges = base.SaveChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        return countChanges;
    }
}

Для новых записей, которые отлично работают, но не для измененных.

Новое значение даты и времени в ChangedDate поле появляется только в контексте, но не записывается в базу данных. Если я перейду через код, я вижу item.State является EntityState.Modified и countChanges возвращаемое значение равно 1, а значение в item.Entity все кажется правильным. Если запросить объект, новое значение будет видно, но значение в базе данных не изменится, поэтому, если я выберу свой контекст, старое значение появится снова.

Действительно сбивает с толку тот факт, что значение поля, которое я изменяю в пользовательском интерфейсе, чтобы проверить его , изменяется в БД, но не в поле. ChangedDate,

Зачем?

Вот пример одного класса сущности и конфигурации, созданной Devarts Entity Devloper:

public partial class Abo {

    public Abo()
    {
        OnCreated();
    }

    #region Properties

    public virtual global::System.Guid Id
    {
        get;
        set;
    }

    // ...

    public virtual global::System.Nullable<System.DateTime> ChangedDate
    {
        get;
        set;
    }

    public virtual global::System.Nullable<System.DateTime> CreatedDate
    {
        get;
        set;
    }

    public virtual string CreatedUser
    {
        get;
        set;
    }

    public virtual string ChangedUser
    {
        get;
        set;
    }
}   


public partial class AboConfiguration : EntityTypeConfiguration<Abo>
{

    public AboConfiguration()
    {
        this
            .HasKey(p => p.Id)
            .ToTable("Abos", "dbo");
        // Properties:
        this
            .Property(p => p.Id)
                .IsRequired()
                .HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)
                .HasColumnType("uniqueidentifier");

        // ...
        this
            .Property(p => p.CreatedDate)
                .HasColumnType("datetime");
        this
            .Property(p => p.ChangedDate)
                .HasColumnType("datetime");
        this
            .Property(p => p.CreatedUser)
                .HasMaxLength(32)
                .HasColumnType("varchar");
        this
            .Property(p => p.ChangedUser)
                .HasMaxLength(32)
                .HasColumnType("varchar");

        OnCreated();
    }

    partial void OnCreated();

}

SQL DDL соответствующей таблицы:

CREATE TABLE [dbo].[Abos](
    [Id] [uniqueidentifier] NOT NULL,
/* .. */
    [ChangedDate] [datetime] NULL,
    [CreatedDate] [datetime] NULL,
    [ChangesUser] [varchar](32) NULL,
    [CreatedUser] [varchar](32) NULL
 CONSTRAINT [PK_dbo.Abos] 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]
GO

2 ответа

Решение

На этом этапе изменения свойств объекта-сущности, полученные средством отслеживания изменений, не относятся к DTO. Вы должны применить изменения через DbEntityEntry.CurrentValues Собственность вместо.

item.CurrentValues["ChangedDate"] = DateTime.Now;

Вам нужно вызвать context.savechanges, чтобы сохранить данные в БД

Другие вопросы по тегам