从ViewController保存时,无法从ObjectStateEntry获取Namespace

时间:2017-07-22 01:34:50

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

我正在尝试为我的MVC,Entity Framework网站项目创建审核日志。我已经能够在我的DBContext中订阅/images/(并通过另一个DBContext但相同的数据库保存到我的数据库中)。

我最后的两个问题是:

  • SaveChanges()到底做了什么?我有一个ViewModel,在保存时将其计算为if (!entry.IsRelationship),将另一个计算为True。我希望这会移到我的方法的其余部分以保存在审核日志中。
  • 如何修改对象的完整命名空间?我正在使用这个:False但在从视图模型保存/编辑时似乎不起作用(详情如下)

这是我到目前为止的基本设置(entry.Entity.ToString()对象/控制器有效,但Album没有):

Ablum课程:

AlbumView

AblumView类:

public class Album : BaseObject //BaseObject has a few properties, one is Oid (Guid)
{
    public string Name { get; set; }

    [Column(TypeName = "varchar(MAX)")]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [Display(Name="Genres")]
    public virtual ICollection<AlbumsGenres> AlbumGenres { get; set; }

    [Display(Name="Artists")]
    public virtual ICollection<AlbumsArtists> AlbumArtists { get; set; }
}

AlbumsController(Audit使用类似的东西):

public class AlbumView
{
    [ScaffoldColumn(false)]
    public Guid Oid { get; set; }

    [Required]
    public string Name { get; set; }

    [Column(TypeName = "varchar(MAX)")]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [Display(Name = "Genres")]
    public virtual List<AlbumsGenres> AlbumGenres { get; set; }

    [Display(Name = "Artists")]
    public virtual List<AlbumsArtists> AlbumArtists { get; set; }

}

AlbumsViewController:

public ActionResult Edit(Album album)
{
    if (ModelState.IsValid)
    {
        db.Entry(album).State = EntityState.Modified;
        db.SaveChanges(); //This is where SaveChanges() takes over (see below)
        return RedirectToAction("Index");
    }
    return View(album);
}

在我的DbContext中的db.SaveChanges():

public ActionResult Edit(Guid id, AlbumView albumViewModel)
{
    //Omitting setup...

    //Album gets updated
    Album album = db.Albums.Find(id);
    album.Name = albumViewModel.Name;
    album.Description = albumViewModel.Description;

    //Other Objects are also updated, just an example:
    albumArtists = new AlbumsArtists();
    albumArtists.Oid = Guid.NewGuid();
    albumArtists.Album = db.Albums.Find(id);
    albumArtists.Artist = db.Artists.Find(item.Artist.Oid);

    //In the end it calls:
    db.SaveChanges();

    //Omitting other stuff...
}

public class ApplicationDBContext : DbContext { public ApplicationDBContext() : base("name=DefaultConnection") { } public System.Data.Entity.DbSet<ContentPub.Models.Music.Album> Albums { get; set; } //Other DBSet objects... public DbSet Set(string name) { return base.Set(Type.GetType(name)); } public override int SaveChanges() { ApplicationLogDBContext logDb = new ApplicationLogDBContext(); ChangeTracker.DetectChanges(); ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext; List<ObjectStateEntry> objectStateEntryList = ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted) .ToList(); foreach (ObjectStateEntry entry in objectStateEntryList) { Guid oid = Guid.Empty; try { if (!entry.IsRelationship) //I don't understand this (first of my two questions) { switch (entry.State) { //Removed other cases case EntityState.Modified: { oid = (Guid)entry.EntityKey.EntityKeyValues[0].Value; //This is the area that I am having issues (second of the two questions) //Below will work when I call db.SaveChanges() from the AlbumsController, //'entry.Entity.ToString()' will get 'x.Models.Music.Albums' and begin a query var query = this.Set(entry.Entity.ToString()).AsNoTracking().Where("Oid == @0", oid); //The issue with the above is when I have a ViewModel, returns something like // = System.Data.Entity.DynamicProxies.Album_AF81C390156ACC8283ECEC668AFB22C4AD621EF70F8F64641D56852D19755BF3 //If the proper Namespace is returned, the next line works and Audit continues var query = this.Set(entry.EntitySet.ElementType.ToString()).AsNoTracking().Where("Oid == @0", oid); //Does a bunch of AuditLog stuff if the above issue doesn't fail break; } } } } catch (Exception ex) { throw new Exception("Log Error (" + entry.Entity.ToString() + ") - " + ex.ToString()); } } return base.SaveChanges(); } } 会返回如下内容:

entry.Entity.ToString()

在AlbumView中我正在更新专辑,以及一堆其他对象。不确定为什么它不会返回System.Data.Entity.DynamicProxies.Album_AF81C390156ACC8283ECEC668AFB22C4AD621EF70F8F64641D56852D19755BF3 ,是否有解决办法,有人可以解释或指向我尚未找到的其他资源吗?

1 个答案:

答案 0 :(得分:0)

虽然它不是最有效的解决方案,但它现在仍然是一种解决方案。

我能够在db.SaveChanges()方法中执行以下操作:

//When AlbumView .BaseType was able to return x.Models.Music.Album
string strNamespace = entry.Entity.GetType().BaseType.ToString(); 

//Needed this if I was updating just an Object (ie: Album),
//would be nice to make something more concret
if (strNamespace == "x.Models.Core.BaseObject")
    strNamespace = entry.Entity.ToString();

//Continuing code
var query = this.Set(strNamespace).AsNoTracking().Where("Oid == @0", oid);

在发布此问题之前,我从另一个问题中找到了答案here