[Mono-list] Serializable object with Non-Serializable Fields --> SerializationException
Jacek Rużyczka
stacheldraht at interia.pl
Wed Jun 2 07:51:25 EDT 2010
Hi folks,
for my .NET remoting app, I am developing a class, which is gonna fetch some
data from an RDBMS (by using DataSet objects) and make a report out of it. Of
course, the class needs to be serializable, so it carries the [Serializable]
attribute.
But: For the database access, it needs to use ADO.NET classes like
IDataAdapter and DataSet...and these classes are NOT serializable. As you can
see from my source-code (DBConnectionHandler is a home-brewn (serializable)
class doing the database connection work for me), the corresponding variables
are defined within the Start() method, so that they are no instance fields.
This is my source code:
using System;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using Npgsql;
using iwawi.batchjobs;
namespace iwawi.batchjobs.server
{
/// <summary>
/// This batch job generates a receipt (except payment reminder, which is
done by
/// PrintPaymentReminder).
/// </summary>
[Serializable]
public class PrintReceipt : MarshalByRefObject, IBatchJob
{
[NonSerialized]
private DBConnectionHandler handler;
private string uri = "";
private string description = "Beleg (ausgenommen Mahnung)
erstellen";
public PrintReceipt()
{
if (ServerInfo.isVerbose) Console.WriteLine
(DateTime.Now.ToString() + ": Serverobjekt PrintReceipt initialisiert.");
}
public string URI {
get {
return this.uri;
}
set {
this.uri = value;
}
}
public string Description {
get {
return this.description;
}
}
public DBConnectionHandler BackendConnectionHandler {
set {
this.handler = value;
}
}
public bool Delay {
get {
return true;
}
}
public bool Repeat {
get {
return false;
}
}
public bool Start (string startingParams)
{
string paramString = this.uri.Substring(this.uri.IndexOf ('?') +
1);
string [] parameters = paramString.Split('&', '=');
string receiptIDList = "";
int i = 1;
if (ServerInfo.isVerbose) Console.WriteLine(DateTime.Now.ToString() + ":
iwawi://batchjobs/" + this.URI +
" gestartet.");
foreach (string x in parameters) {
if (i % 2 == 1 && x == "receipt_id_list") {
receiptIDList = "ARRAY [" + x + "]";
}
i++;
}
if (receiptIDList.Length == 0) {
this.CallingBack(this, new CallBackArgs(false, "Pflicht-Parameter
receipt_id_list fehlt."));
return false;
}
else {
IDictionary args = new Hashtable(1);
IDictionary receiptData = new Hashtable();
args.Add("receipt_id_array", receiptIDList);
try {
Skeleton headerSkel = new Skeleton(108, this.handler);
Skeleton boilerplateSkel = new Skeleton(107, this.handler);
Skeleton contactDataSkel = new Skeleton(109, this.handler);
Skeleton receiptSkel = new Skeleton(110, this.handler);
Skeleton lineItemSkel = new Skeleton(111, this.handler);
Skeleton printSkel = new Skeleton(112, this.handler);
IDbCommand cmd = this.handler.CreateCommand();
cmd.CommandText = "SELECT separator FROM
appdata.phone_number_separator;";
args.Add("phone_number_separator", cmd.ExecuteScalar());
IDataAdapter adapter = this.handler.CreateDataAdapter
(receiptSkel.Process(args));
DataSet dataSet = new DataSet("receipt_body");
adapter.Fill(dataSet);
DataRow row = dataSet.Tables [0].Rows [0];
foreach (DataColumn col in dataSet.Tables [0].Columns) {
receiptData.Add(col.ColumnName, row [col.ColumnName]);
if (col.ColumnName == "receipt_language_id" || col.ColumnName ==
"clerk_person_id") {
args.Add(col.ColumnName, row [col.ColumnName]);
}
}
adapter = this.handler.CreateDataAdapter (headerSkel.Process(args));
dataSet = new DataSet("receipt_header");
adapter.Fill(dataSet);
row = dataSet.Tables [0].Rows [0];
foreach (DataColumn col in dataSet.Tables [0].Columns) {
receiptData.Add(col.ColumnName, row [col.ColumnName]);
}
adapter = this.handler.CreateDataAdapter (boilerplateSkel.Process(args));
dataSet = new DataSet("receipt_texts");
adapter.Fill(dataSet);
row = dataSet.Tables [0].Rows [0];
foreach (DataColumn col in dataSet.Tables [0].Columns) {
receiptData.Add(col.ColumnName, row [col.ColumnName]);
}
IDictionary contactData = new Hashtable();
receiptData.Add("clerk_contact_data", contactData);
adapter = this.handler.CreateDataAdapter (contactDataSkel.Process(args));
dataSet = new DataSet("contact_data_header");
adapter.Fill(dataSet);
foreach (DataRow contactDataRow in dataSet.Tables [0].Rows) {
contactData.Add(contactDataRow ["position_key"], contactDataRow
["position_value"]);
}
IDictionary lineItemData = new Hashtable();
receiptData.Add("line_items", lineItemData);
adapter = this.handler.CreateDataAdapter (lineItemSkel.Process(args));
dataSet = new DataSet("line_items");
adapter.Fill(dataSet);
int j = 0;
foreach (DataRow lineItemRow in dataSet.Tables [0].Rows) {
IDictionary lineItem = new Hashtable();
lineItemData.Add(j, lineItem);
foreach (DataColumn col in dataSet.Tables [0].Columns) {
lineItem.Add(col.ColumnName, lineItemRow [col.ColumnName]);
}
j++;
}
adapter = null;
return true;
}
catch (NpgsqlException ex) {
string errorMessage = "Beleg konnte nicht erstellt werden. Ursache: \n" +
ex.Message + "\n\n" +
ex.StackTrace;
this.CallingBack(this, new CallBackArgs(false, errorMessage));
if (ServerInfo.isVerbose) Console.WriteLine(DateTime.Now.ToString() + ": "
+ errorMessage);
return false;
}
}
}
public event BatchJob.CallBackHandler CallingBack;
}
}
And when I start my app, this happens:
Marshaling pressed signal
Exception in Gtk# callback delegate
Note: Applications can use GLib.ExceptionManager.UnhandledException to
handle the exception.
System.Reflection.TargetInvocationException: Exception has been thrown by the
target of an invocation. --->
System.Runtime.Serialization.SerializationException: Type
Npgsql.NpgsqlDataReader in assembly Npgsql, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=5d8b90d52f46fda7 is not marked as serializable. at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke
(System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg, System.Exception&
exc, System.Object[]& out_args) [0x00000] in <filename unknown>:0
What I don't really understand: Why are my ADO.NET objects *inside* the
Start() method serialized? And: How do I make Mono keeps its hands off these
objects when serializing? The attribute [NonSerialized] only applies to
instance fields...
Thank you for any useful hints.
Regards
Jacek Rużyczka
----------------------------------------------------------------------
Sprawdz, co masz zapisane w swoich dloniach!
>>> http://linkint.pl/f2713
More information about the Mono-list
mailing list