所有
我收到"收藏被修改;枚举操作可能无法执行。"在我的对象图的序列化过程中(它在SerializeDictionary()上失败了,但是我的对象图中没有字典)。我正在使用Newtonsoft序列化来序列化我的对象图。
我知道异常意味着什么,在查看我的对象图后,我想在Newtonsoft json序列化程序中可能存在一个错误。下面我发布了整个堆栈跟踪。这是有趣的细节。我设置了另一个测试用例来解决问题,令我惊讶的是我没有收到序列化异常。相同的对象图,相同的序列化程序,只是不同的项目环境。以下是2个案例,1个作品,其他不起作用。在这两种情况下,我都从数据库加载精确的对象图形!
案例1:序列化失败
Visual Studio:2012专业版
asp.net 3.5(CLR 2)
Serializer:Newtonsoft
项目类型:Web应用程序
案例2:序列化工作
Visual Studio:2005 Pro
asp.net 2.0(CLR 2)
Serializer:Newtonsoft
项目类型:控制台应用
序列化代码:
Receipt rec = ReceiptManager.LoadReceipt(26157);
var result = Newtonsoft.Json.JsonConvert.SerializeObject(rec,
new Newtonsoft.Json.JsonSerializerSettings
{
settings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
});
模型(看你能否发现错误):
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
/// <summary>
/// Represents a document in accounting.
/// </summary>
[Serializable()]
public class Document
{
private string _documentNumber = "";
private DateTime _documentDate;
private string _currencyCode;
public Document()
{
}
public Document(string documentNumber)
{
_documentNumber = documentNumber;
}
public string DocumentNumber
{
get { return _documentNumber; }
set { _documentNumber = value; }
}
public DateTime DocumentDate
{
get { return _documentDate; }
set { _documentDate = value; }
}
public string CurrencyCode
{
get { return _currencyCode; }
set { _currencyCode = value; }
}
}
}
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
[Serializable()]
public class Receipt : Document
{
private int _id;
private long _versionNumber;
private ProjectInfo _project;
private ClientInfo _client;
private PaymentMethod _paymentMethod;
private string _referenceNo;
private string _chequeNo;
private Money _amountReceived;
private string _comment;
private string _templateFile; // used to render this document (ie. read-only/printing)
// accounting export related
private bool _posted;
private string _accountingId; // The internal id of the payment as it is in the accounting system.
private string _accountingBatchId;
private DateTime? _transactionDate;
private string _transactionId;
private int? _transactionNumber;
private PostingStatus? _postStatus;
private string _postingUser; // user name that posted this document
private ReceiptLineItemCollection _lineItems = new ReceiptLineItemCollection();
public Receipt()
{
_id = -1;
}
public Receipt(string currencyCode)
{
_id = -1;
CurrencyCode = currencyCode;
}
public int Id
{
get { return _id; }
set { _id = value; }
}
public long VersionNumber
{
get { return _versionNumber; }
set { _versionNumber = value; }
}
public ProjectInfo Project
{
get { return _project; }
set { _project = value; }
}
public ClientInfo Client
{
get { return _client; }
set { _client = value; }
}
public PaymentMethod PaymentMethod
{
get { return _paymentMethod; }
set { _paymentMethod = value; }
}
public string ReferenceNo
{
get { return _referenceNo; }
set { _referenceNo = value; }
}
public string ChequeNo
{
get { return _chequeNo; }
set { _chequeNo = value; }
}
public Money AmountReceived
{
get { return _amountReceived; }
set { _amountReceived = value; }
}
public string Comment
{
get { return _comment; }
set { _comment = value; }
}
public string TemplateFile
{
get { return _templateFile; }
set { _templateFile = value; }
}
public bool Posted
{
get { return _posted; }
set { _posted = value; }
}
public string AccountingId
{
get { return _accountingId; }
set { _accountingId = value; }
}
public string AccountingBatchId
{
get { return _accountingBatchId; }
set { _accountingBatchId = value; }
}
public DateTime? TransactionDate
{
get { return _transactionDate; }
set { _transactionDate = value; }
}
public string TransactionId
{
get { return _transactionId; }
set { _transactionId = value; }
}
public int? TransactionNumber
{
get { return _transactionNumber; }
set { _transactionNumber = value; }
}
public PostingStatus? PostStatus
{
get { return _postStatus; }
set { _postStatus = value; }
}
public string PostingUser
{
get { return _postingUser; }
set { _postingUser = value; }
}
public ReceiptLineItemCollection LineItems
{
get { return _lineItems; }
set { _lineItems = value; }
}
public ReceiptLineItem FindReceiptLine(int invoiceId)
{
foreach (ReceiptLineItem lineItem in _lineItems)
{
if (lineItem.Invoice.Id == invoiceId)
return lineItem;
}
return null;
}
}
}
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
public class ReceiptLineItemCollection : List<ReceiptLineItem>
{
}
}
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
public class ReceiptLineItem
{
private InvoiceDetailedSummary _invoice;
private Money _amountAppliedToInvoice;
private Receipt _receipt;
public ReceiptLineItem()
{
}
public ReceiptLineItem(Receipt receipt)
{
if (receipt == null)
throw new ArgumentNullException("receipt");
_receipt = receipt;
}
public InvoiceDetailedSummary Invoice
{
get { return _invoice; }
set { _invoice = value; }
}
public Money AmountAppliedToInvoice
{
get { return _amountAppliedToInvoice; }
set { _amountAppliedToInvoice = value; }
}
[Obsolete("TODO: To be removed in future release.")]
public Receipt Receipt
{
get { return _receipt; }
set { _receipt = value; }
}
}
}
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
/// <summary>
/// Lightweight object that contains brief invoice summary.
/// </summary>
[Serializable()]
public class InvoiceBriefSummary
{
public const string PROP_INVOICEID = "Id";
public const string PROP_INVOICEDATE = "InvoiceDate";
public const string PROP_INVOICENUMBER = "InvoiceNumber";
public const string PROP_CURRENCYCODE = "CurrencyCode";
public const string PROP_GRANDTOTAL = "GrandTotal";
private int _id;
private DateTime _invoiceDate;
private string _invoiceNumber;
private string _currencyCode;
public InvoiceBriefSummary()
{
}
public InvoiceBriefSummary(Invoice invoice)
{
if (invoice == null)
throw new ArgumentNullException("invoice");
_id = invoice.Id;
_invoiceDate = invoice.DocumentDate;
_invoiceNumber = invoice.DocumentNumber;
_currencyCode = invoice.CurrencyCode;
}
public InvoiceBriefSummary(InvoiceHeader invoice)
{
if (invoice == null)
throw new ArgumentNullException("invoice");
_id = invoice.Id;
_invoiceDate = invoice.InvoiceDate;
_invoiceNumber = invoice.InvoiceNumber;
_currencyCode = invoice.CurrencyCode;
}
public int Id
{
get { return _id; }
set { _id = value; }
}
public DateTime InvoiceDate
{
get { return _invoiceDate; }
set { _invoiceDate = value; }
}
public string InvoiceNumber
{
get { return _invoiceNumber; }
set { _invoiceNumber = value; }
}
public string CurrencyCode
{
get { return _currencyCode; }
set { _currencyCode = value; }
}
}
}
namespace PrlSystems.PimarcCore.DomainModel.Commerce
{
/// <summary>
/// XML serializer friendly detailed invoice summary.
/// </summary>
[Serializable()]
public class InvoiceDetailedSummary : InvoiceBriefSummary
{
private ContactInfo _billTo;
private ProjectInfo _project;
private decimal _subtotal;
private decimal _grandtotal;
private decimal _taxtotal;
private string _accountingId;
private string _transactionId;
private int? _transactionNumber;
public InvoiceDetailedSummary()
{
}
public InvoiceDetailedSummary(Invoice invoice)
: base(invoice)
{
_billTo = invoice.BillToAddress;
_project = invoice.Project;
_subtotal = invoice.Subtotal.Amount;
TaxCalculator calculator = new TaxCalculator();
TaxSummary tax = calculator.GetDocumentTax(invoice);
_taxtotal = tax.Taxes.GetTotalTax().Amount;
_grandtotal = invoice.GetGrandtotal(tax).Amount;
_accountingId = invoice.AccountingId;
_transactionId = invoice.TransactionId;
_transactionNumber = invoice.TransactionNumber;
}
public InvoiceDetailedSummary(InvoiceHeader invoice)
: base(invoice)
{
_billTo = invoice.BillTo.GetContactInformation();
_project = invoice.Project.GetProjectInfo();
_project.ClientId = invoice.Client.Id; // use client ID on the invoice
_subtotal = invoice.Subtotal;
_grandtotal = invoice.Grandtotal;
_accountingId = invoice.AccountingId;
_transactionId = invoice.TransactionId;
_transactionNumber = invoice.TransactionNumber;
}
public ContactInfo BillTo
{
get { return _billTo; }
set { _billTo = value; }
}
public ProjectInfo Project
{
get { return _project; }
set { _project = value; }
}
public decimal Subtotal
{
get { return _subtotal; }
set { _subtotal = value; }
}
public decimal Taxtotal
{
get { return _taxtotal; }
set { _taxtotal = value; }
}
public decimal Grandtotal
{
get { return _grandtotal; }
set { _grandtotal = value; }
}
public string AccountingId
{
get { return _accountingId; }
set { _accountingId = value; }
}
public string TransactionId
{
get { return _transactionId; }
set { _transactionId = value; }
}
public int? TransactionNumber
{
get { return _transactionNumber; }
set { _transactionNumber = value; }
}
}
}
完成堆栈跟踪:
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, JsonSerializerSettings settings)
at Pimarcnet.UserControls.Invoicing.ReceiptForm.get_ViewModel() in c:\PRL\DEV\Visual Studio 2012\Pimarcnet35\Pimarcnet35\UserControls\Invoicing\ReceiptForm.ascx.cs:line 42
at ASP.usercontrols_invoicing_receiptform_ascx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in c:\PRL\DEV\Visual Studio 2012\Pimarcnet35\Pimarcnet35\UserControls\Invoicing\ReceiptForm.ascx:line 164
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)
at System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Page.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
--- End of inner exception stack trace ---
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.pages_invoicing_editreceipt2_aspx.ProcessRequest(HttpContext context) in c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\07d8779e\a6e74bf1\App_Web_hhnohwoa.4.cs:line 0
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
答案 0 :(得分:1)
所有,我找到了造成这种异常的罪魁祸首,而且这并不容易。张贴让其他人受益。
在Receipt类中,PaymentMethod属性(特别是类型)导致序列化程序爆炸。当收据对象被水合时(来自数据库实体),引用的PaymentMethod属性实际上指向一个懒惰加载的数据库实体(即引用一个hibernate代理)。当序列化器序列化对象图时,hibernate正在注入导致错误的真实实体,至少这就是我的想法。
它仍然没有解释以下内容(我没有时间进一步调查,因为我需要完成项目):
1)在我的其他环境中,这不是问题。
2)至于踢,我(以非懒惰的方式)加载了一个PaymentMethod对象列表并尝试序列化...这再次触发了异常。 PaymentMethod类具有很少的简单属性,并且它不会引用任何其他可能延迟加载的实体。有趣的是,我尝试加载一个帐户列表(另一种类型,大部分都是相同的字段)并序列化。这有效!真奇怪。
故事的寓意:
如果你看到&#34;收藏被修改;枚举操作可能无法执行&#34;,查看您的对象图,看看您是否正在引用可能会延迟加载的对象。如果您仍然无法解决问题,请简化对象图,即。而不是嵌套复杂对象,从嵌套到根对象的字段中提取字段并序列化根。这正是我发现问题的方式。