EntityFramework - 实体代理错误

时间:2012-09-07 09:20:01

标签: c# entity-framework

我正在研究使用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正确加载,并且所有属性都已加载。

实体报价看起来有点像这样:

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; }
}

3 个答案:

答案 0 :(得分:36)

当我尝试在我的实体上实现ICloneable并使用MemberwiseClone克隆它时,我也遇到了这种情况。当我使用我自己实例化的实体时工作得很好。但是,当我使用它来克隆使用EF加载的实体时,每当我尝试将其添加到DbSet(或其他各个部分)时,我都会收到此错误。

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

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

修改

这是我为解决此问题而创建的一个片段。请注意,这样做只会复制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;

    }

答案 1 :(得分:1)

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

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

我希望它也适合你。

答案 2 :(得分:0)

I solved it this way.

using (var ctx = new MyContext())
      {
         ctx.Configuration.ProxyCreationEnabled = false;

         return ctx.Deferrals.AsNoTracking().Where(r => 
         r.DeferralID.Equals(deferralID)).FirstOrDefault();
      }