EntityFramework CreatedOn 属性 只能在 SaveChanges 方法中设置

EntityFramework CreatedOn property can be set only in SaveChanges method

我有一个名为 Entity 的模型对象,我将其用作我的基础 class。

[Serializable]
public class Entity
{
    [Key]
    public int Id { get; set; }
    [Required]
    public DateTime? ModifiedOn { get; set; }
    [Required]
    public DateTime? CreatedOn { get; set; }
}

然后我像这样覆盖了SaveChanges方法,所以每次我创建新记录时CreatedOn 属性都会自动设置。

public override int SaveChanges()
{
    ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
    foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
    {
        var entity = entry.Entity as Entity;
        if(entry.State == EntityState.Added)
        {
            entity.CreatedOn = DateTime.UtcNow;
        }
        entity.ModifiedOn = DateTime.UtcNow;
    }
    return base.SaveChanges();
}

我的问题是如何防止在其他地方设置 CreatedOnModifiedOn 属性,SaveChanges 方法除外。例如,这是不允许的:

Entity entity = new Entity { CreatedOn = DateTime.UtcNow, ModifiedOn = DateTime.UtcNow };
context.Entities.Add(entity);
context.SaveChanges();

有两种方法可以做到这一点
1)使您的 DbContext 成为嵌套的 class(这样您就可以访问外部 class 的私有字段)
2)使用反射(正如@Hamlet Hakobyan 所建议的那样)

示例 1

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
namespace ConsoleApplication3
{
   class Program
   {
       public static void Main()
       {
            Entity.MyContext context = new Entity.MyContext();
            context.Entities.Add(new Entity());
            // context.Entities.Add(new Entity() { Created = DateTime.Now }); //Does not compile
            context.SaveChanges();
        }
   }

    [Serializable]
    public class Entity
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public DateTime? Created { get; private set; }

        public class MyContext : DbContext
        {
            public DbSet<Entity> Entities { get; set; }

            public override int SaveChanges()
            {
                ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
                foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
                {
                    var entity = entry.Entity as Entity;
                    if (entry.State == EntityState.Added)
                        entity.Created = DateTime.Now;
                }
                return base.SaveChanges();
            }
        }
    }
}

示例 2

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;

namespace ConsoleApplication3
{
    class Program
    {
        public static void Main()
        {
            MyContext context = new MyContext();
            context.Entities.Add(new Entity()); // CreatedOn = DateTime.Now does not compile
            context.SaveChanges();
            Console.ReadLine();
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<Entity> Entities { get; set; }

        public override int SaveChanges()
        {
            ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
            foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
            {
                var entity = entry.Entity as Entity;
                if (entry.State == EntityState.Added)
                    entity.GetType().GetProperty("CreatedOn").SetValue(entity, DateTime.Now);
            }
            return base.SaveChanges();
        }
    }

    [Serializable]
    public class Entity
    {
        [Key]
        public int Id { get; set; }

        [Required]
        public DateTime? CreatedOn { get; private set; }
   }
}