Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EntityFramework没有';刷新导航属性_C#_.net_Entity Framework 4 - Fatal编程技术网

C# EntityFramework没有';刷新导航属性

C# EntityFramework没有';刷新导航属性,c#,.net,entity-framework-4,C#,.net,Entity Framework 4,我有一段简单的关系 我用上面的模型创建了一个简单的应用程序。应用程序中的模型必须在每次数据库更改时更新。我可以通过调用GetDBChanges存储过程来获取最新的更改。(见方法T11) 以下是应用程序: class Program { private static int? _lastDbChangeId; private static readonly MASR2Entities Model = new MASR2Entities(); private static

我有一段简单的关系

我用上面的模型创建了一个简单的应用程序。应用程序中的模型必须在每次数据库更改时更新。我可以通过调用GetDBChanges存储过程来获取最新的更改。(见方法T11)

以下是应用程序:

class Program
{
    private static int? _lastDbChangeId;
    private static readonly MASR2Entities Model = new MASR2Entities();
    private static readonly Timer T1 = new Timer(1000);
    private static readonly Timer T2 = new Timer(1000);
    private static Strategy _strategy = null;

    static void Main(string[] args)
    {
        using (var ctx = new MASR2Entities())
        {
            _lastDbChangeId = ctx.GetLastDbChangeId().SingleOrDefault();
        }
        _strategy = Model.Strategies.FirstOrDefault(st => st.StrategyId == 224);

        T1.Elapsed += T1Elapsed;
        T1.Start();

        T2.Elapsed += T2Elapsed;
        T2.Start();

        Console.ReadLine();
    }

    static void T2Elapsed(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("All rules: " + Model.StrategyRules.Count());
        Console.WriteLine("Strategy: name=" + _strategy.Name + " RulesCount=" + _strategy.StrategyRules.Count);
    }

    private static void T1Elapsed(object sender, ElapsedEventArgs e)
    {
        T1.Stop();
        try
        {
            using (var ctx = new MASR2Entities())
            {
                var changes = ctx.GetDBChanges(_lastDbChangeId).ToList();
                foreach (var dbChange in changes)
                {
                    Console.WriteLine("DbChangeId:{0} {1} {2} {3}", dbChange.DbChangeId, dbChange.Action, dbChange.TableName, dbChange.TablePK);
                    switch (dbChange.TableName)
                    {
                        case "Strategies":
                            {
                                var id = Convert.ToInt32(dbChange.TablePK.Replace("StrategyId=", ""));
                                Model.Refresh(RefreshMode.StoreWins, Model.Strategies.AsEnumerable());
                            }
                            break;
                        case "StrategyRules":
                            {
                                var id = Convert.ToInt32(dbChange.TablePK.Replace("StrategyRuleId=", ""));
                                Model.Refresh(RefreshMode.StoreWins, Model.StrategyRules.AsEnumerable());
                            }
                            break;
                    }
                    _lastDbChangeId = dbChange.DbChangeId;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("ERROR: " + ex.Message);
        }
        finally
        {
            T1.Start();
        }
    }
}
当我运行它时,这是一个示例输出:

All rules: 222
Strategy: name=Blabla2 RulesCount=6
然后我在子表中添加一行(策略规则)

最后,我将该行从StrategyRules中删除

DbChangeId:1714 D StrategyRules StrategyRuleId=811
All rules: 222
Strategy: name=Blabla2 RulesCount=7
为什么RuleScont仍然是7?如何强制EF刷新“导航属性”

我错过了什么

——编辑---以涵盖Slauma的答案

case "StrategyRules":
{
   var id = Convert.ToInt32(dbChange.TablePK.Replace("StrategyRuleId=", ""));
   if (dbChange.Action == "I")
   {
       //Model.Refresh(RefreshMode.StoreWins, Model.StrategyRules.AsEnumerable());       
   }
   else if (dbChange.Action == "D")
   {
      var deletedRule1 = Model.StrategyRules.SingleOrDefault(sr => sr.Id == id); 
      //the above one is NULL as expected

      var deletedRule2 = _strategy.StrategyRules.SingleOrDefault(sr => sr.Id == id);
      //but this one is not NULL - very strange, because _strategy is in the same context
      //_strategy = Model.Strategies.FirstOrDefault(st => st.StrategyId == 224);
   }  
}

ObjectContext.Refresh
刷新传递到方法中的实体的标量属性。如果您传递到方法中的某个实体在数据库中不再存在,因为它同时已被删除
刷新
不会对附加的实体执行任何操作,只会忽略它。(这是我的猜测,但我无法解释为什么1)在
刷新
时没有出现异常(例如“无法刷新实体,因为它已被删除”),以及2)实体显然仍然附加到上下文。)

您的Insert案例不起作用,因为您调用了
Refresh
,但它起作用,因为您将整个
StrategyRules
表加载到此行的内存中:

Model.Refresh(RefreshMode.StoreWins, Model.StrategyRules.AsEnumerable())
Refresh
在内部枚举第二个参数中的集合。通过启动迭代,它触发查询,该查询只是
Model.StrategyRules
=加载整个表
AsEnumerable()
只是从LINQ到实体再到LINQ到对象的切换,也就是说,在
AsEnumerable()
之后应用的每个LINQ操作符都是在内存中执行的,而不是在数据库中执行的。由于不应用任何内容,
AsEnumerable()
实际上对查询没有影响

因为您加载了整个表,所以最近插入的
StrategyRule
也将被加载,并且一起将是
\u strategy
实体的键。
ObjectContext
的自动关系修复程序在
\u strategy
\u strategy.StrategyRules.Count
中建立与导航集合的关系。(您可以删除
Refresh
调用,只需调用
Model.StrategyRules.ToList()
,结果仍然是
7

现在,所有这些在Delete情况下都不起作用。您仍然可以运行一个查询来从数据库加载整个
StrategyRules
表,但EF不会从上下文中删除或分离不再在结果集中的实体。(据我所知,没有强制自动删除的选项。)被删除的实体仍在上下文中,其键引用
策略
,计数将保持
7

我想知道的是,为什么您不利用您的
DBChanges
集合显然确切地知道在
dbChange.TablePK
属性中删除了哪些内容。除了使用
Refresh
之外,您是否可以使用以下内容:

case "StrategyRules":
{
    switch (dbChange.Action)
    {
        case "D":
        {
            var removedStrategyRule = _strategy.StrategyRules
                .SingleOrDefault(sr => sr.Id == dbChange.TablePK);
            if (removedStrategyRule != null)
                _strategy.StrategyRules.Remove(removedStrategyRule);
        }
        break;

        case ...
    }
}
break;

首先非常感谢你的解释。这是有道理的,你是对的,我不需要调用Refresh(没有它也会有同样的行为),但是你如何解释:Model.StrategyRules.SingleOrDefault(sr=>sr.Id==myId)在DB delete之后为null,而_strategy.StrategyRules.SingleOrDefault(sr=>sr.Id==myId)在notnull中为null(它仍然保存“deleted”规则)。基本上_strategy.StrategyRules.Count=7,但Model.StrategyRules.ToList()返回6项。那么它是否会从上下文中移除?我会在早上添加更多的代码,让它更清晰。其次,很好的建议与开关情况“D”的东西,但我没有_战略目标。(这只是一个例子)。我也不能做Model.Strategies.SingleOrDefault(s=>s.Id==??);因为不知道StrategyId(仅StrategyRuleId)。我正在考虑通过调用Model.StrategyRules.SingleOrDefault(sr=>sr.Id==myID)获取strategy对象。strategy失败,因为StrategyRule为null(已从上下文中删除)@Novitzky:对于您的第一条评论。删除的规则不会从上下文中删除
Model.StrategyRules.ToList()
查询数据库,而不是上下文条目。因此,它返回除已删除的规则->计数=6之外的所有内容
\u strategy.StrategyRules
是内存中的对象图,它仍然具有已删除的规则->计数=7。再次感谢。我做了一些测试,它的工作原理和你解释的一模一样。
case "StrategyRules":
{
    switch (dbChange.Action)
    {
        case "D":
        {
            var removedStrategyRule = _strategy.StrategyRules
                .SingleOrDefault(sr => sr.Id == dbChange.TablePK);
            if (removedStrategyRule != null)
                _strategy.StrategyRules.Remove(removedStrategyRule);
        }
        break;

        case ...
    }
}
break;