【问题标题】:EntityFramework - Entity proxy errorEntityFramework - 实体代理错误
【发布时间】:2014-05-23 15:35:27
【问题描述】:

我正在使用 Entityframework 开发一个系统,现在已经超过 12 个月了,该项目一直进展顺利,直到昨天,我现在遇到了一个奇怪的错误,我不知道它为什么会发生。 我所做的与我之前所做的没有什么不同,但是一旦我加载有问题的实体并尝试访问任何子实体,我就会收到以下错误:

The entity wrapper stored in the proxy does not reference the same proxy

任何人都可以阐明这实际上意味着什么以及会导致这种情况的原因吗?

显示我的代码并没有真正的帮助。

下面是简化版的代码:

var quote = new QuoteHelper().GetById(orderId);
var updatedQuotes = new Provider().GetExportQuotes(quote.DeparturePoint.Id,quote.DestinationPoint);

访问 DeparturePoint 和 DestinationPoint 时出现错误,但 Quote 正确加载,并且所有属性都已加载。

实体 Quote 看起来有点像这样:

public class Quote : BaseQuote, ICloneable
{
     public Guid DeparturePointId { get; set; }
     public virtual LocationPoint DeparturePoint{ get; set; }

     public Guid DestinationPointId { get; set; }
     public virtual LocationPoint DestinationPoint{ get; set; }
}

【问题讨论】:

    标签: c# entity-framework


    【解决方案1】:

    当我尝试在我的实体上实现 ICloneable 并使用 MemberwiseClone 克隆它时,这也发生在我身上。当我使用我自己实例化的实体时效果很好。但是,当我使用它克隆已使用 EF 加载的实体时,每当我尝试将其添加到 DbSet(或其他各种部分)时都会收到此错误。

    经过一番挖掘,我发现当你克隆一个 EF 加载的实体时,你也在克隆代理类。代理类携带的一件事是对给定实体的包装器的引用。因为浅拷贝只复制对包装器的引用,所以您突然有了两个具有相同包装器实例的实体。

    此时,EF 认为您已经为您的实体创建或借用了不同的代理类,它认为这是为了恶作剧并阻止您。

    编辑

    这是我为解决此问题而创建的一个 sn-p。请注意,这将完成仅复制 EF 属性的公平工作,但这并不完美。请注意,如果您还有必须复制的私有字段,则需要对其进行修改,但您明白了。

        /// <summary>
        /// Makes a shallow copy of an entity object. This works much like a MemberwiseClone
        /// but directly instantiates a new object and copies only properties that work with
        /// EF and don't have the NotMappedAttribute.
        /// </summary>
        /// <typeparam name="TEntity">The entity type.</typeparam>
        /// <param name="source">The source entity.</param>
        public static TEntity ShallowCopyEntity<TEntity>(TEntity source) where TEntity : class, new()
        {
    
            // Get properties from EF that are read/write and not marked witht he NotMappedAttribute
            var sourceProperties = typeof(TEntity)
                                    .GetProperties()
                                    .Where(p => p.CanRead && p.CanWrite &&
                                                p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.NotMappedAttribute), true).Length == 0);
            var newObj = new TEntity();
    
            foreach (var property in sourceProperties)
            {
    
                // Copy value
                property.SetValue(newObj, property.GetValue(source, null), null);
    
            }
    
            return newObj;
    
        }
    

    【讨论】:

    • 谢谢,我有一个可怕的克隆方法,而且成员方面似乎我需要的魔法似乎不是。谢谢。
    • MemberwiseClone 通常是您需要的魔法,但 EF 会做一些独特的事情。顺便说一句,如果您发现此解决方案还不够,我还听说有人使用AutoMapper 来获取廉价的克隆机制。它不是为此而设计的,但这并不意味着它不是一个完美的解决方案。
    • 谢谢,我已经解决了这个问题,但是当我有时间回来解决它时,我将实施您提供的解决方案之一。感谢您的洞察力,在这个问题上似乎没有太多内容,我希望这对其他人也有帮助。
    • 使用 NotMappedAttribute 属性,转至stackoverflow.com/questions/12194267/…
    • “System.ComponentModel.DataAnnotations.NotMappedAttribute”不应该是“System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute”吗?
    【解决方案2】:

    可能会出现上述解决方案,例如错误“已检测到关系 y 的角色 x 发生冲突更改”。我使用这种方法实现了这个错误;

     public virtual TEntity DetachEntity(TEntity entityToDetach)
        {
            if (entityToDetach != null)
                context.Entry(entityToDetach).State = EntityState.Detached;
            context.SaveChanges();
            return entityToDetach;
        }
    

    我希望它也对你有用。

    【讨论】:

      【解决方案3】:

      我是这样解决的。

      using (var ctx = new MyContext())
            {
               ctx.Configuration.ProxyCreationEnabled = false;
      
               return ctx.Deferrals.AsNoTracking().Where(r => 
               r.DeferralID.Equals(deferralID)).FirstOrDefault();
            }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-23
        • 2011-03-30
        相关资源
        最近更新 更多