gpt4 book ai didi

c# - 为什么我的 EF 分离不够?

转载 作者:行者123 更新时间:2023-11-30 17:55:41 25 4
gpt4 key购买 nike

我尝试分离 group 类型的实体。

实际上我将它保存在我的缓存中,并在响应客户端之前分离它。

在下一个请求中,我从缓存中获取 group 并重新附加一个新的 objectContext。

但是我得到 一个实体对象不能被 IEntityChangeTracker 的多个实例引用

我知道附加包括所有相关实体,但分离不包括。在那里我必须分离每个相关实体。

我的分离中缺少什么?

这是我的实体层次结构:

public partial class App
{
public App()
{
this.Pairs = new HashSet<Pair>();
}

public string AppName { get; set; }
public System.Guid AppGuid { get; set; }
public string ClientAppID { get; set; }
public bool IsDeleted { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
public Nullable<System.DateTime> UpdatedDate { get; set; }

public virtual AppsData AppsData { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}


public partial class AppsData
{
public System.Guid AppGuid { get; set; }
public string Url { get; set; }
public string DisplayName { get; set; }
public string AppDesc { get; set; }
public string PrivacyPolicyUrl { get; set; }
public string TermsOfUseUrl { get; set; }
public string LocalizationKey { get; set; }
public string Compatibility { get; set; }
public bool HiddenApp { get; set; }
public bool IsExperimental { get; set; }

public virtual App App { get; set; }
}

public partial class Browser
{
public Browser()
{
this.BrowserVersions = new HashSet<BrowserVersion>();
}

public int BrowserID { get; set; }
public string BrowserName { get; set; }
public string BrowserCode { get; set; }

public virtual ICollection<BrowserVersion> BrowserVersions { get; set; }
}

public partial class BrowserVersion
{
public BrowserVersion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
}

public System.Guid BrowserVersionID { get; set; }
public int BrowserID { get; set; }
public string Version { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public Nullable<int> Group_Id { get; set; }

public virtual Browser Browser { get; set; }
public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
}

public partial class BrowserVerToCriteria
{
public System.Guid CriteriaID { get; set; }
public System.Guid BrowserVersionID { get; set; }
public string ConditionBrowserVersion { get; set; }

public virtual BrowserVersion BrowserVersion { get; set; }
public virtual Criterion Criterion { get; set; }
}

public partial class CommonConfig
{
public int ID { get; set; }
public string NAME { get; set; }
public string VALUE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public byte GROUP_ID { get; set; }
public string DESCRIPTION { get; set; }
}

public partial class Country
{
public Country()
{
this.Criteria = new HashSet<Criterion>();
this.Criteria1 = new HashSet<Criterion>();
}

public int CountryID { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }

public virtual ICollection<Criterion> Criteria { get; set; }
public virtual ICollection<Criterion> Criteria1 { get; set; }
}

public Criterion()
{
this.BrowserVerToCriterias = new HashSet<BrowserVerToCriteria>();
this.Countries = new HashSet<Country>();
this.CountriesExceptions = new HashSet<Country>();
this.Pairs = new HashSet<Pair>();
}

public System.Guid CriteriaID { get; set; }
public string Domains { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public string DomainsExclude { get; set; }

public virtual ICollection<BrowserVerToCriteria> BrowserVerToCriterias { get; set; }
public virtual ICollection<Country> Countries { get; set; }
public virtual ICollection<Country> CountriesExceptions { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}

public partial class CTID
{
public string CTID1 { get; set; }
public string AppVersion { get; set; }
}

public partial class CtidPgPastExistence
{
public string Ctid { get; set; }
}

public partial class Group
{
public Group()
{
this.Pairs = new HashSet<Pair>();
}

public System.Guid GroupId { get; set; }
public int TestId { get; set; }
public int IdInTest { get; set; }
public bool WelcomeExperienceEnabledByDefault { get; set; }

public virtual MamConfiguration MamConfiguration { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}

public partial class MamConfiguration
{
public MamConfiguration()
{
this.Groups = new HashSet<Group>();
this.MamConfigurationCTIDs = new HashSet<MamConfigurationCTID>();
}

public int TestID { get; set; }
public string TestName { get; set; }
public string Description { get; set; }
public int StatusId { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime UpdatedDate { get; set; }
public bool IsProd { get; set; }
public int TestTraffic { get; set; }

public virtual ICollection<Group> Groups { get; set; }
public virtual MamConfigurationStatus MamConfigurationStatus { get; set; }
public virtual ICollection<MamConfigurationCTID> MamConfigurationCTIDs { get; set; }
}

public partial class MamConfigurationCTID
{
public int TestID { get; set; }
public string CTID { get; set; }

public virtual MamConfiguration MamConfiguration { get; set; }
}

public partial class MamConfigurationStatus
{
public MamConfigurationStatus()
{
this.MamConfigurations = new HashSet<MamConfiguration>();
}

public int StatusId { get; set; }
public string Status { get; set; }

public virtual ICollection<MamConfiguration> MamConfigurations { get; set; }
}

public partial class Pair
{
public Pair()
{
this.Groups = new HashSet<Group>();
}

public System.Guid PairID { get; set; }
public System.Guid CriteriaID { get; set; }
public System.Guid AppGuid { get; set; }

public virtual App App { get; set; }
public virtual Criterion Criterion { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}

public partial class SettingsServicesConfig
{
public int ID { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public int Interval { get; set; }
public System.DateTime UPDATED_DATE { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public int GROUP_ID { get; set; }
}

这是我的分离函数:

public void Detach<T>(MaMDBEntities maMdbEntities, T item) where T : class, new()
{
switch (typeof (T).Name.ToLower())
{
case "group":
{
var group = item as Group;

if (group == null)
{
mApplicationLogger.Error(string.Format("Couldn't cast item to type 'Group'"));

throw new InvalidCastException(string.Format("Couldn't cast item to type 'Group'"));
}

DetachState(maMdbEntities, group.MamConfiguration);

foreach (var pair in group.Pairs.ToList())
{
DetachState(maMdbEntities, pair.App);

DetachState(maMdbEntities, pair.App.AppsData);

foreach (var country in pair.Criterion.Countries.ToList())
{
DetachState(maMdbEntities, country);
}

foreach (var country in pair.Criterion.CountriesExceptions.ToList())
{
DetachState(maMdbEntities, country);
}


foreach (var browserVerToCriterias in pair.Criterion.BrowserVerToCriterias.ToList())
{
DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion.Browser);

DetachState(maMdbEntities, browserVerToCriterias.BrowserVersion);

DetachState(maMdbEntities, browserVerToCriterias);
}

DetachState(maMdbEntities, pair.Criterion);

DetachState(maMdbEntities, pair);

}

break;
}
}
maMdbEntities.Entry(item).State = EntityState.Detached;
}

private static void DetachState(MaMDBEntities maMdbEntities, object item)
{
maMdbEntities.Entry(item).State = EntityState.Detached;
}

最佳答案

我相信您需要确保您的上下文中没有任何实体引用任何已分离的实体。因此,如果说,其他东西引用了 Pair 的分离实例,上下文会很高兴地找到它,遍历它的导航属性并将所有内容添加回去。

您是否尝试过设置 State 属性:

((IObjectContextAdapter)maMdbEntities).ObjectContext.Detach(item);

除了项目本身之外,这应该会分离到要分离的项目的任何链接。

编辑

好吧,让我们看看“detach any links to the item being detached ...”,ObjectContext.Detach最终调用了这个方法:

// System.Data.Objects.EntityEntry
internal void Detach()
{
base.ValidateState();
bool flag = false;
RelationshipManager relationshipManager = this._wrappedEntity.RelationshipManager;
flag = (base.State != EntityState.Added && this.IsOneEndOfSomeRelationship());
this._cache.TransactionManager.BeginDetaching();
try
{
relationshipManager.DetachEntityFromRelationships(base.State);
}
finally
{
this._cache.TransactionManager.EndDetaching();
}
this.DetachRelationshipsEntries(relationshipManager);
IEntityWrapper wrappedEntity = this._wrappedEntity;
EntityKey entityKey = this._entityKey;
EntityState state = base.State;
if (flag)
{
this.DegradeEntry();
}
else
{
this._wrappedEntity.ObjectStateEntry = null;
this._cache.ChangeState(this, base.State, EntityState.Detached);
}
if (state != EntityState.Added)
{
wrappedEntity.EntityKey = entityKey;
}
}

DetachEntityFromRelationships 分解所有链接。ObjectContext.Detach 上的文档没有具体说明链接的拆除 http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.detach.aspx它确实说“调用 Detach 方法后,系统将不再保留指向该对象的引用,它可以由垃圾收集器收集”,这意味着所有 LinkDescriptors 也将被删除。

关于您的第 3 条评论“您认为 IObjectContextAdapter 将启用完全分离。还是上下文中总会有其他对象我会错过而不是分离?”这里有两件事;有对象的属性和上下文用来跟踪关系的 LinkDescriptor。分离只是通过分离链接描述符来停止跟踪对象的关系,它不会分离关系另一端的对象。它也不会将此类属性设置为 null,如果您在分离后检查对象,它仍会设置这些属性。

这是最好的方法吗?分离和重新连接很难正确。如果您需要分离和重新附加,我建议您将深度分离程序移动到类本身而不是通用方法中。

就是说,您写了“在下一个请求时,我从缓存中获取组...”这让我想知道两次请求之间的最长时间段是多少?你能通过缓存引入并发问题吗?您是否在 IIS 中托管 WCF 服务?如果并发不是问题,您可以使用 IIS 的缓存吗?您是否在同一线程上处理所有请求?您可能不知道 ObjectContext 实例方法不是线程安全的。

关于c# - 为什么我的 EF 分离不够?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14800140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com