使用 Entity Framework 4.1 创建历史表

发布于 2024-12-14 18:50:00 字数 180 浏览 2 评论 0原文

我正在开发 asp.net MVC 3 应用程序,并且使用 codeFirst 方法。我正在尝试创建历史表或用户表,我想在其中跟踪用户修改了哪些列。我如何使用 EF Code First 来做到这一点。

我需要在 DataContext.savechanges 之后执行此操作吗?

请建议。

谢谢。

I am working on asp.net MVC 3 application and I am using codeFirst approach. I am trying to create history table or user table, Where I want to keep track of what columns were modified by user. How can I do this using EF Code First.

Do I need to do it after DataContext.savechanges ?

Please suggest.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

莫言歌 2024-12-21 18:50:06

在我看来,您想要一个继承自 ActionFilterAttribute 的过滤器。就我而言,这是我拥有的最简单的例子。这是我的模型,请注意属性决定了到数据库的映射。

[Table("UserProfile")]
public class UserProfile
{
    [Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    public string UserName { get; set; }
}

就我而言,它就像下面这样简单,尽管它不是历史性的:

public sealed class UsersContext : DbContext
{
    public UsersContext() : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        LazyInitializer.EnsureInitialized(ref _initializer, ref isInitialized, ref initializerLock);
    }

        public void CheckDatabase()
        {
            Database.SetInitializer<YourDBContextType>(null);

            using (var context = new YourDBContextType())
            {
                if (!context.Database.Exists())
                {
                        ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                }
            }

// Uses your connection string to build the following table. 
 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
        }

最终结果不仅是 EF 是代码优先,而且还允许您的视图模型使用从复杂实体派生的基元。现在,如果您有另一个(比如说历史数据库)DBContext,那么我建议您修改文本转换文件或为您的实体创建一个基类。这两种方法都可以轻松生成可以插入表中的代码,然后跟踪该实体,将其克隆到历史模型中并保存。话虽这么说,我是数据库优先方法的粉丝,专注于约束、触发器等,而不是框架。

Sounds to me like you want an a filter that inherits from ActionFilterAttribute. In my case, this is the simplest example that I have. This is my model, notice that the attributes dictate the mapping to the database.

[Table("UserProfile")]
public class UserProfile
{
    [Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    public string UserName { get; set; }
}

In my case, it was as simple as the following, although it was not historical:

public sealed class UsersContext : DbContext
{
    public UsersContext() : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        LazyInitializer.EnsureInitialized(ref _initializer, ref isInitialized, ref initializerLock);
    }

        public void CheckDatabase()
        {
            Database.SetInitializer<YourDBContextType>(null);

            using (var context = new YourDBContextType())
            {
                if (!context.Database.Exists())
                {
                        ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                }
            }

// Uses your connection string to build the following table. 
 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
        }

The end result is not only EF being code first, but also allows for your models for your views to use primitives derived from your complex entities. Now, if you have another, lets say historical, DBContext then I would recommend modifying either the text transformation file or creating a base class for your entities. Both ways allow for an easy generation of code that could insert into your table, then follow up with that entity, clone it into a historical model and save. All that being said, I am a fan of database first approaches with concentration on constraints, triggers, etc. instead of a framework.

つ可否回来 2024-12-21 18:50:05

DbContext 有一个名为 Entry 的方法:

var entity = context.Items.Find(id);
entity.Name = "foobar";

var entry = context.Entry<Item>(entity);

条目的类型为 DbEntityEntry 并具有属性 OriginalValues当前值

您可能可以编写一些内容来一般性地检查这些属性以查看发生了什么变化,然后自动将新记录插入到历史表中。

要么使用数据库触发器。

The DbContext has a method called Entry<T>:

var entity = context.Items.Find(id);
entity.Name = "foobar";

var entry = context.Entry<Item>(entity);

entry will be of type DbEntityEntry<T> and has the properties OriginalValues and CurrentValues.

You could probably write something that will generically inspect these properties to see what has changed and then automatically insert a new record into your history table.

Either that, or use database triggers.

巴黎夜雨 2024-12-21 18:50:05

我不确定这是否真的是“适当”的方法,但这就是它通常在 sql 中完成的方式:

  1. 创建 int 类型或其他类型的额外属性 version
  2. 因为您可能不想每次都循环,所以添加另一个 bool 类型的属性 IsLatestVersion
  3. 当保存实体时,检查该实体是否已存在。如果是这样,请将实体设置为 IsLatestVersion = false。
  4. 增加版本,并将更改保存为新实体。

I'm not sure if this is really the "appropiate" way to do it, but this is how its usually done in sql:

  1. Create an extra property version of type int or something.
  2. Because you probably do not want to loop every time, add another property IsLatestVersion of type bool
  3. When an entity is saved, check if the entity already exists. If so, set the entity on IsLatestVersion = false.
  4. Increment the version, and save the changes as new entity.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文