我使用实体框架为项目创建了一个原型,现在它可以正常工作了,我想使程序可以投入生产。

我在EF方面面临许多挑战,其中最大的挑战是并发管理(这是一种财务软件)。

鉴于似乎无法用EF处理悲观并发,我不得不切换到SQL中的存储过程。

老实说,我有点担心可能带来的工作量。

我想知道以前是否有人遇到过相同情况,以及使用EF将.net代码转换为原始SQL的最佳策略是什么?

编辑:我正在研究CLR,但尚不清楚是否可以使用它来管理悲观的并发性。 在这种情况下,它是否比TSQl更有趣? 如果我理解得很清楚,它将使我可以重用部分C#代码和调用另一个函数的函数结构。

===============>>#1 票数:1 已采纳

我在那里,好消息是,如果您不想的话,您不必放弃Entity Framework。 坏消息是您必须自己更新数据库。 这并不像看起来那么难。 我目前正在使用EF 5,但计划使用EF6。我不明白为什么这对于EF 6仍然不起作用。

第一件事是在DbContext的构造函数中将其强制转换为IObjectContextAdapter并获得对ObjectContext的访问权。 我为此做一个财产

public virtual ObjectContext ObjContext
{
    get
    {
        return ((IObjectContextAdapter)this).ObjectContext;
    }
}

一旦您订阅了SavingChanges事件-这不是我们的确切代码,则某些内容将从其他方法中复制出来并重做。 这只是让您了解需要做什么。

ObjContext.SavingChanges += SaveData;

private void SaveData(object sender, EventArgs e)
{
    var context = sender as ObjectContext;
    if (context != null)
    {
        context.DetectChanges();
        var tsql = new StringBuilder();
        var dbParams = new List<KeyValuePair<string, object>>();

        var deletedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
        foreach (var delete in deletedEntites)
        {
            // Set state to unchanged - so entity framework will ignore
            delete.ChangeState(EntityState.Unchanged);
            // Method to generate tsql for deleting entities
            DeleteData(delete, tsql, dbParams);
        }

        var addedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
        foreach (var add in addedEntites)
        {
            // Set state to unchanged - so entity framework will ignore
            add.ChangeState(EntityState.Unchanged);
            // Method to generate tsql for added entities
            AddData(add, tsql, dbParams);
        }

        var editedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
        foreach (var edit in editedEntites)
        {
            // Method to generate tsql for updating entities
            UpdateEditData(edit, tsql, dbParams);
            // Set state to unchanged - so entity framework will ignore
            edit.ChangeState(EntityState.Unchanged);
        }
        if (!tsql.ToString().IsEmpty())
        {
            var dbcommand = Database.Connection.CreateCommand();
            dbcommand.CommandText = tsql.ToString();

            foreach (var dbParameter in dbParams)
            {
                var dbparam = dbcommand.CreateParameter();
                dbparam.ParameterName = dbParameter.Key;
                dbparam.Value = dbParameter.Value;
                dbcommand.Parameters.Add(dbparam);
            }
            var results = dbcommand.ExecuteNonQuery();
        }
    }
}

为什么我们在更新后将实体设置为未修改,因为您可以

var changed properties = edit.GetModifiedProperties();

获取所有已更改属性的列表。 由于所有实体现在都标记为未更改,因此EF将不会向SQL发送任何更新。

您还需要弄乱元数据,以便从实体到表,从属性到字段。 这并不是很难,但是弄乱元数据确实需要一些时间来学习。 有时我仍在挣扎。 我将所有内容重构为IMetaDataHelper接口,在其中将其传递给实体类型和属性名称以获取表和字段-以及缓存结果,因此我不必一直查询元数据。

最后,tsql是一个批处理,它具有所有T-SQL,包括锁定提示并包含事务级别,这是我们想要的方式。 如果用户也将数字字段更新为2,则我们也将数字字段从刚设置为nfield = 10更改为nfield = nfield + 2(在TSQL中),也避免了并发问题。

一旦有人开始编辑您的实体,您将无法锁定SQL,但是我也看不到如何通过存储过程来实现。

总而言之,我花了大约2天的时间才能完成所有准备工作。

  ask by Caribou translate from so

未解决问题?本站智能推荐:

关注微信公众号