在ASP MVC中是否有等效的Rails ActiveRecord :: Callbacks?

时间:2013-02-21 21:40:02

标签: asp.net-mvc entity-framework

在ASP MVC中是否有等效的Rails ActiveRecord :: Callback?

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

我遇到的情况是我们没有使用主键的身份。我们这样做是出于特定于DB分片设计的原因。因此,我们有一个查找表来查找特定表的下一个ID。我想自动获取此值,并在创建/更新模型时以及保存之前将其设置为抽象类。保存成功后,我还需要使用递增的'nextID'更新查找表。

如果没有回调,我也会接受其他解决方案。

2 个答案:

答案 0 :(得分:0)

所以你需要回调只是为了增加查找表中的ID? AFAIK在ASP.NET中没有等效的,可能你可以尝试使用异步控制器(http://msdn.microsoft.com/en-us/library/ee728598%28v=vs.100%29.aspx)并等待成功保存的状态更改,但我更喜欢使用专门为此服务的服务,如Snowflake({ {3}})。

答案 1 :(得分:0)

我找到了一个使用覆盖而不是回调的解决方案。我希望ASP mvc在框架继续成熟时增加对回调的支持,因为回调通过允许OnSave事件存在于事件所关注的模型[s]而不是集中式DbContext类中而允许更清晰的代码(分离问题)。

<强>解决方案:

可以在Context类中重写SaveChanges方法(Entity Framework Power Tools创建Context类是'Models'目录。)

    public override int SaveChanges()
    {
        // create a cache for id values in case their are multiple added entries in the dbcontext for the same entitytype
        Dictionary<string, UniqueID> idCache = new Dictionary<string, UniqueID>();
        IEnumerable<DbEntityEntry> changes = this.ChangeTracker.Entries();
        foreach (var entry in changes)
        {
            //check if this is a new row (do nothing if its only a row update because there is no id change)
            if (entry.State == System.Data.EntityState.Added)
            {
                //determine the table name and ID field (by convention)
                string tableName = entry.Entity.GetType().Name;
                string idField = entry.Entity.GetType().Name + "ID";
                UniqueID id = null;
                //if we've already looked this up, then use the cache
                if (idCache.ContainsKey(tableName))
                {
                    id = idCache[tableName];
                }
                //if we havn't looked this up before get it and add it to the cache
                else
                {
                    id = this.UniqueIDs.Find(tableName, idField);
                    //if it doesn't already exist in the lookup table create a new row
                    if (id == null)
                    {
                        id = new UniqueID(tableName, idField, 1);
                        // since this is a new entry add it
                        this.UniqueIDs.Add(id);
                    }
                    else
                    {
                        // set the state to modified
                        this.Entry(id).State = System.Data.EntityState.Modified;
                    }
                }
                entry.CurrentValues[tableName + "ID"] = id.NextID;
                id.NextID = id.NextID + 1;
            }

        }
        return base.SaveChanges();
    }