【问题标题】:How to populate complex types as soon as the entity is inserted/modified?插入/修改实体后如何填充复杂类型?
【发布时间】:2014-09-04 08:02:38
【问题描述】:

我的实体类中包含了这个Complex Type,例如:

public class Logbook
{
  public string CreatedBy { get; set; }
  public DateTimeOffset DateCreated { get; set; }
  public string ModifiedBy { get; set; }
  public DateTimeOffset DateModified { get; set; }
}

然后是我的主课:

public class Customer
{
  public int Id { get; set; }
  public string Name { get; set; }
  public Logbook Logbook { get; set; }
}

然后我将Logbook 类设置为复杂类型。我的问题是,我想知道如何在插入/修改Customer 实体后立即设置Logbook 中的值?比如说,将DateCreated 设置为DateTime.UtcNow 并将CreatedBy 设置为用户名......等等。任何帮助将非常感激。谢谢!

编辑:

我使用Entity Framework 进行数据访问。这就是我保存Customer

的方法
public ActionResult Create(Customer customer)
{
  if ( Model.IsValid() )
  {
    _customerRepository.Insert(customer);
    return View("Index");
  }

  return View(customer);
}

【问题讨论】:

  • 你能展示你创建一个新Customer的代码吗?
  • 保存Customer之前还是之后?
  • 插入/更新是什么意思?实体框架?你使用存储库还是什么?
  • ps。还有很多关于此的有趣文章:google.com/…

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


【解决方案1】:

我不知道是否可以自动完成。就我而言,我准备了一个特殊的通用方法来处理日志中的实体更新(在每种情况下它都是 IoC 友好的:)):

public T PrepareLogbookProperty<T>(T model)
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }

    var dynamicModel = (dynamic)model;

    Entity value;

    try
    {
        value = dynamicModel.Logbook as Logbook;
    }
    catch (RuntimeBinderException)
    {
        throw new NoLogbookPropertyFound();
    }

    value = this.PassLog(value); // THAT METHOD PASSES CURRENT USER OR DATE TIME.

    dynamicModel.Logbook= value;

    return model;
}

它有一个缺点——不幸的是它是动态的。为了处理其他情况,我准备了其他重载函数:

public TEntity PrepareLogbookProperty<TEntity>(TEntity model, Expression<Func<TEntity, Logbook>> entityExpression)
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }

    var memberExpression = (MemberExpression)entityExpression.Body;
    var property = (PropertyInfo)memberExpression.Member;

    var value = property.GetValue(model) as Logbook;
    value = this.PassLog(value);

    property.SetValue(model, value);

    return model;
}

用法:

this.helper.PrepareLogbookProperty(customer, cust => custom.MyOtherLogBook); // expression version

this.helper.PrepareLogbookProperty(product); // dynamic version (I assume that product has Logbook property

在每个SaveChanges() 之前手动调用方法。

不幸的是,我无法更改数据库架构及其设计方式 - 因此该解决方案适合我。

样本通过日志:

private Logbook PassLog(Logbook entity)
{
    if (entity == null)
    {
        entity = this.NewLogbook();
    }

    entity.EditedDate = this.dateTimeProvider.Now;
    entity.EditorID = this.services.CurrentUser.ID;

    return entity;
}

【讨论】:

    【解决方案2】:

    你在追求这样的事情吗?

    public class Logbook
    {
      public Logbook(string username)
      {
        this.CreatedBy = username;
        this.DateCreated = DateTime.UtcNow; //NB: ideally your database would provide this to ensure if deployed on multiple servers you'd have one date source
        this.ModifiedBy = username;
        this.DateModified = DateTime.UtcNow; //as above
      }
      public void Modify(string username)
      {
        this.ModifiedBy = username;
        this.DateModified = DateTime.UtcNow; //as above
      }
      public string CreatedBy { get; set; }
      public DateTimeOffset DateCreated { get; set; }
      public string ModifiedBy { get; set; }
      public DateTimeOffset DateModified { get; set; }
    }
    
    public class Customer
    {
      private int id;
      public int Id { 
        get { return this.id; } 
        set { this.id = value; this.OnCreateOrModify(); }
      }
    
      private string name;
      public string Name { 
        get { return this.name; }
        set { this.name = value; this.OnCreateOrModify(); }
      }
      public Logbook Logbook { get; private set; } //presumably you don't want other classes to amend this
      private void OnCreateOrModify()
      {
        var username = System.Environment.UserName;  //or pass something into your class contructor to provide a username
        if (this.Logbook == null) //create
            this.Logbook = new LogBook(username);
        else //modify
            this.Logbook.Modify(username);
      }
    }
    

    【讨论】:

    • 嗯,数据库优先呢?从数据库中更新每个模型,我都会手动编辑生成的实体类,我认为这是不推荐的。
    • 嗨。谢谢。但是你能解释一下这条线吗? set { this.id = value; this,OnCreateOrModify(); }
    • @BoyPasmo 错字;逗号应该是一个点。这会为属性(在本例中为 id)分配一个值,并确保相关的审计条目得到相应更新。
    • @p 不确定; EF 对我来说很新,所以我的答案基于我在 EF 之前所做的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多