简体   繁体   English

EntityFramework - 实体代理错误

[英]EntityFramework - Entity proxy error

I am working on a system using Entityframework and have been for over 12monts now, and the project has been going well, up until yesterday, where I have now got a strange error which I have no idea why it occurs.我正在使用 Entityframework 开发一个系统,现在已经超过 12 个月了,项目进展顺利,直到昨天,我现在遇到了一个奇怪的错误,我不知道它为什么会发生。 I am doing nothing different to what I have done before, but once I load the entity in question and try to access any child entities I get the following error:我所做的与之前所做的没有什么不同,但是一旦我加载了有问题的实体并尝试访问任何子实体,我就会收到以下错误:

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

Can anyone shed any light on what this actually means and what would cause this?任何人都可以阐明这实际上意味着什么以及会导致这种情况的原因吗?

Showing my code doesnt really help.显示我的代码并没有真正的帮助。

Here is a simplified version of the code:这是代码的简化版本:

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

The error occurs when accessing DeparturePoint and DestinationPoint but Quote loads correctly, and all properties are loaded.访问 DeparturePoint 和 DestinationPoint 时发生错误,但 Quote 加载正确,并且加载了所有属性。

The entity Quote looks a little like this:实体 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; }
}

This happened to me too when I tried to implement ICloneable on my entity and cloned it using MemberwiseClone.当我尝试在我的实体上实现 ICloneable 并使用 MemberwiseClone 克隆它时,这也发生在我身上。 Worked great when I was using entities that I instantiated myself.当我使用我自己实例化的实体时效果很好。 However, when I used this to clone an entity that had been loaded using EF, I got this error whenever I tried to add it to a DbSet (or in various other parts).但是,当我使用它来克隆使用 EF 加载的实体时,每当我尝试将它添加到 DbSet(或其他各种部分)时,我都会收到此错误。

After some digging, I found that when you clone an EF-loaded entity, you're cloning the proxy class as well.经过一番挖掘,我发现当您克隆一个 EF 加载的实体时,您也在克隆代理类。 One of the things a proxy class carries around is a reference to the wrapper fo the given entity.代理类携带的一件事是对给定实体的包装器的引用。 Because a shallow copy only copies a reference to the wrapper, you suddenly have two entities that have the same wrapper instance.由于浅拷贝仅复制对包装器的引用,因此您会突然拥有两个具有相同包装器实例的实体。

At this point, EF thinks you've created or borrowed a different proxy class for your entity which it assumes is for purposes of mischief and blocks you.在这一点上,EF 认为您已经为您的实体创建或借用了不同的代理类,它认为这是为了恶作剧并阻止您。

Edit编辑

Here's a snippet that I created to work around this problem.这是我为解决此问题而创建的一个片段。 Note that this will do a fair job of copying just the EF properties, but it's not perfect.请注意,这可以很好地复制 EF 属性,但它并不完美。 Note that you'll need to modify it if you have private fields that must be copied as well, but you get the idea.请注意,如果您也有必须复制的私有字段,则需要修改它,但您明白了。

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

    }

Above solution may occur such as error " Conflicting changes to the role x of the relationship y have been detected ".上述解决方案可能会出现错误“已检测到关系 y 的角色 x 的冲突更改”。 I achieve that error with using this method;我使用此方法实现了该错误;

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

i hope it'll work for you too.我希望它也适合你。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM