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
_______________________________________________
Mono-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-list