MVC3-实体对象不能被ientitychangetracker的多个实例引用
本文关键字:实例 引用 ientitychangetracker 实体 对象 不能 MVC3- | 更新日期: 2023-09-27 18:24:09
我经历了类似的问题,但它能解决我的目的。我在两个方面使用相同的代码:1。直接通过按钮按下2。通过计划任务。
通过方法1,它工作良好,但方法2给出了该误差。我的代码:
服务-
public virtual int SendCampaign(Campaign campaign, EmailAccount emailAccount,
IEnumerable<NewsLetterSubscription> subscriptions)
{
var campaignSubscriberTrack = new CampaignNewsletterSubscriberTrack();
if (campaign == null)
throw new ArgumentNullException("campaign");
if (emailAccount == null)
throw new ArgumentNullException("emailAccount");
int totalEmailsSent = 0;
foreach (var subscription in subscriptions)
{
var tokens = new List<Token>();
_messageTokenProvider.AddStoreTokens(tokens);
_messageTokenProvider.AddNewsLetterSubscriptionTokens(tokens, subscription);
string subject = _tokenizer.Replace(campaign.Subject, tokens, false);
string body = _tokenizer.Replace(campaign.Body, tokens, true);
var email = new QueuedEmail()
{
Priority = 3,
From = emailAccount.Email,
FromName = emailAccount.DisplayName,
To = subscription.Email,
Subject = subject,
Body = body,
CreatedOnUtc = DateTime.UtcNow,
EmailAccountId = emailAccount.Id
};
_queuedEmailService.InsertQueuedEmail(email);
totalEmailsSent++;
campaignSubscriberTrack.CampaignId = campaign.Id;
campaignSubscriberTrack.NewsletterSubscriberId = subscription.Id;
campaignSubscriberTrack.Campaign = campaign;
campaignSubscriberTrack.NewsletterSubscription = subscription;
campaignSubscriberTrack.IsEmailOpened = 0;
campaignSubscriberTrack.OpenedOnUtc = null;
Guid guid;
string id = tokens.Where(t => t.Key.Equals("TrackImage")).Select(t => t.Value).FirstOrDefault();
var lastPart = (id.Split('/').Last()).Split('=').Last();
if (lastPart != null)
{
guid = new Guid(lastPart);
campaignSubscriberTrack.ImageGUID = guid;
}
***InsertCampaignNewsletterSubscriberTrack(campaignSubscriberTrack);***
}
campaign.CampaignSchedulingTime = 0;
UpdateCampaign(campaign);
return totalEmailsSent;
}
类别-
public partial class CampaignNewsletterSubscriberTrack
{
public virtual Campaign Campaign { get; set; }
public virtual int CampaignId { get; set; }
public virtual NewsLetterSubscription NewsletterSubscription { get; set; }
public virtual int NewsletterSubscriberId { get; set; }
public virtual int IsEmailOpened { get; set; }
public virtual DateTime? OpenedOnUtc { get; set; }
public virtual Guid ImageGUID { get; set; }
}
}
型号-
public class CampaignNewsletterSubscriberTrackModel
{
public int CampaignId { get; set; }
public int NewsletterSubscriberId { get; set; }
public int IsEmailOpened { get; set; }
public DateTime? OpenedOnUtc { get; set; }
public Guid ImageGUID { get; set; }
}
在这个函数中,记录被插入-
public virtual void InsertCampaignNewsletterSubscriberTrack(CampaignNewsletterSubscriberTrack track)
{
if (track == null)
throw new ArgumentNullException("track");
_campaignNewsletterSubscriberTrackRepository.Insert(track);
}
错误发生在-->InsertCampaignNewsletter SubscriberTrack(campaignSubscriberTrack);我该怎么办???有人能告诉我哪里出了问题吗?
我猜您使用的是实体框架。您启用了更改跟踪。在这种情况下,实体对象存储对相应对象上下文的引用
所以campaign
、emailAccount
或subscriptions
是可疑的(如果它们真的是实体的话)。
您可以通过campaignSubscriberTrack
引用这些实体,我想您稍后会尝试将其添加到新的objectContext中。使用外键引用实体,或者在将实体附加到新的objectContext之前分离实体。
更详细:
当您从数据库查询实体时,有几种方式可以影响其状态。
如果您的实体(我猜是POCO)不是一个密封类,并且包含虚拟导航属性,并且启用了代理生成,则会专门生成动态代理来修复实体的关系
如果标量属性也是虚拟的,那么除此之外,DynamicProxy还有助于跟踪更改
每个实体都可以附加到上下文,也可以从上下文分离。当使用AsNoTracking()时,查询返回分离的实体
正如您从异常中看到的,问题出现在变更跟踪器中
因此,如果实体已经连接到另一个上下文,并且更改跟踪处于打开状态,则无法将其连接到上下文。
但如果更改跟踪关闭:没有为POCO生成AsNoTracking()
或代理(context.Configuration.ProxyCreationEnabled = false
),则可以在上下文之间"共享"实体
请注意,禁用propxies并不意味着返回分离的实体。它们将保持附加状态,但只有在调用DetectChanges()时,才会在SaveChanges(()处检测到更改。
因此,这个异常应该告诉您,您使用一个未处理的上下文查询实体,然后尝试将实体图附加到另一个上下文
你必须在代码中找到使用新上下文而不是旧上下文的位置。。。或者在将加载的实体附加到新上下文之前分离它们。