C# Persisting Objects Between User Sessions Without using a database - c#

I'm making a simple Winforms that reads in a text file and does some parsing to put it into C# objects that are then manipulated by my app.
I would like to parse the file once. Then go away for a week, come back and load all the objects back into my app.
I don't want to persist to database thus was hoping there was some sort of simple object persistance framework I could hook into.

You are talking about serialization.
Look into the DataContractSerializer for this. If you want a file that isn't XML you can try the DataContractJsonSerializer.
You simply add the DataContract and DataMember attributes to tell the serializer how to manage the serialization.
If your objects will not change (new/old/renamed properties and visibility) and you don't care to read the serialization format, you can try the BinaryFormatter.
There are several older serializers in the frame work (XmlSerializer, BinaryFormatter and more), but the best control over the serialization format will be with the above).

You could use application settings or user settings. Its pretty easy with the wizard that can be found under the projects properties. here is the tutorial for it.

You could just serialize them to an XML file. Simple, quick and easy (unless someone hacks the file).

The simplest non-DB method of storing object state is serialization. Mark your class as either Serializable or a DataContract, then use a BinaryFormatter (or DataContractSerializer if you used the DataContract) to convert the object into a persistable state. That can then be saved to a file that you can load when the app starts back up and deserialize in a similar fashion. Be aware that the class's members, including child classes, must be serializable in the same way, and that you will lose any references to non-serialized elements such as pointers and delegate references.

You can use serialization as sugested before.
A good place to save the data in is Windows's LocalData folder -
Environment.SpecialFolder.LocalApplicationData

Probably the simplest way to do this would be to serialize the objects directly to a file, using the BinaryFormatter class. You'll need to make sure that all your types are marked as [Serializable] but this approach is fast and easy.
Here is a simple example of a "read" and "write" method for an arbitrary object graph:
private void SerializeToFile(string fileName, object o)
{
var binaryFormatter = new BinaryFormatter();
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
binaryFormatter.Serialize(fileStream, o);
}
}
private object DeserializeFromFile(string fileName)
{
var binaryFormatter = new BinaryFormatter();
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
return binaryFormatter.Deserialize(fileStream);
}
}
Other approaches include XmlSerialization (the XmlSerializer class) - better if you want to the serialized objects to be human readable or editable, or using the newer DataContractSerializer.

What is wrong with a database ? If you do not want to have a full engine with its setup and associated problems, maybe you can take a look at "file" based databases...
My first toughs are :
SqlCompact
Access databases
SqlLite
...
Depending the complexity of your objects to persist, it can be a good solution.

Related

C# Serializing properties with custom values

I want to serialize a class with a lot of properties. Some of those properties are complex. There are some of the type Bitmap, Color and much more, and they do not get serialized at all.
The approach I am using is the following:
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
MemoryStream stream = new MemoryStream();
serializer.Serialize(stream, obj);
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
XmlDocument returnDoc = new XmlDocument();
returnDoc.Load(stream);
How can I create "custom" approaches for those complex properties? Until now I created the XML-Documents myself and went trough every single property and converted it to text.
An other example where I need this is on references. This class has got some references to other classes. I don't want the whole subclass to be serialized, but only the name of it.
I am sure there are different approaches on how to accomplish this. What would be the best way to go?
I already tought of making extra properties and ignoring the others (XmlIgnore()), but that would be an overhead.
Thanks!
Your best bet is to stop trying to serialize your domain model, and create a DTO model that represents just what you want to store, in the way you want to store it (i.e. geared towards your chosen serializer).
If you want to store a bitmap, then you probably want a byte[] property. If you want to store the name of something - a string. Then just map between them. Simple, pain-free, and much easier than trying to fight a serializer into doing something that it doesn't want to do.
For properties that are not serializable you need to implement the serialization yourself. You could serialize these objects to a byte array and then use Base64 encoding to place them to XML. Check out the following link: XmlSerializer , base64 encode a String member.
However, if you do not need to serialize into XML, you can use binary serialization which will work on all properties.

Saving a collection of SerializableAttributes

I have several Employee objects which are all SerializableAttributes. This is due to WCF, because these are objects passed between the client and the server.
I would now like to save and load several of these, either to a file or by using System.Properties namespace. With the System properties, I could not find a way to save them because the types that are allowed are pretty limited: int, string, float and some others. There's nothing involving serializable, and the only collection available is a string collection.
What would be the best approach? I'm not sure what is the proper way to save a collection, like List<> of SerializableAttributes to a file. Otherwise, I can use System.properties and I could do it the "hard way" by converting the objects to strings and back, but this approach will be pretty ugly.
You have many alternatives such as: JavaScriptSerializer XmlSerializer DataContractSerializer DataContractJsonSerializer BinaryFormatter SoapFormatter.
(BTW: Serializable attribute is only used by BinaryFormatter and no need for WCF)

C# Object Serialization Changes

I have the following issue:
My object is being serialized as follows:
MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, _policy);
CaptureData = Convert.ToBase64String(memorystream.ToArray());
And then saved to my database and de-serialized as required from the data saved in the database.
My problem now is that I can't make changes to this object, add properties etc as this breaks the deserialization.
Any suggestions on how I can add properties without breaking serialization of previous objects?
I don't think it's possible using this serializer.
If possible, use another serializer that deals with backward compatibility like protocol buffers
You can use [OptionalField] and similar to take advantage of the version tolerant serialisation built into .Net.
You need to shift from the built-in serialization , as this is, as you saw, is rigid and not scallable. Pick any other serializaiton technique that let's you maintan scallability of your types and flexibility of your system.
custom binary serialization
xml serialization
json serialization
binary serialization with protobuf (just example...)
All this, if you can do that. If not, for some architectural (historical) restrictions, just can do something like suggested in Hamlet's comment. But it sounds like a rough solution to me.

data access layer using xml files

I want to create a data access layer, supporting CRUD methods, with an underlying storage of XML files.
I'm new to XML, and I'm not quite sure how to work with XmlDocument, XDocument, XmlSerializer etc..
Here's my basic idea for a data access class:
public class EmployeesDao
{
private const string FILE_NAME = "file.xml";
//an XDocument which contains all the employees records
private XDocument m_XDocument;
private XmlSerializer m_XmlSerializer;
public TestCasesDao()
{
//is this correct?
m_XDocument = XDocument.Load(#"c:\" + FILE_NAME);
m_XmlSerializer = new XmlSerializer(typeof(EmployeeDTO));
}
public void Save(IEmployee employee)
{
var dto = new EmployeeDTO(employee);
//TODO: serialize the DTO, add it to the XDocument, and save to file
}
public IEmployee GetEmployee(string name)
{
//TODO: retrieve an EmployeeDTO from my XDocument
return employeeDto.Convert(); //return an IEmployee
}
//TODO: update and delete methods...
}
Any ideas as to how to fill in the missing gaps?
It really depends what your needs are. Using XML for a DAL only makes sense for a small project, and even in this case SQLite might be a better solution. The only "benefit" in XML is that it is a textual, human readable format, but in that sense it serves better as an export file, than an actual DAL technology. The problem with any "hand made" single file DB system is that you need to save the entire file each time you make a change (if you don't opt for memory mapped files, which could be an overkill depending on your needs).
For every insert or update operation, you will need a reader and a writer, in order to copy all records to a new file. Depending on your file size, an option might be to keep the records in memory during your app lifetime, and flush them to disk every once in a while. It would be a statically available list (with concurrency in mind), but it only makes sense if the database is relatively small.
Your biggest concern might be consistency and transactional integrity. If you have two processes using the same XML file simultaneously, it will be hard to synchronize access. Additionally, app crash or a power failure could leave your data corrupted, which means you should also think about some kind of a journaling system. SQLite, for example, as simple as it may seem on first glance, is ACID, and dedicates a great deal of effort to achive this (if you have time, check this lengthy article to get an idea). Implementing this from scratch is a real overkill.
So, to summarize, your options are:
You only have a single process using a single file.
a. Database is small: keep it in memory, lock all operations, and flush it regularly. Relatively simple.
b. Database is large:
use a reader/writer combination to copy the entire file on each operation. Very simple, but slower.
keep a queue of commands and flush them in batches. Faster, adds some transactional support, but complicated.
Another process can access the file.
a. implement a journaling mechanism to prevent simultaneous access.
b. create a separate service which will handle all transactions by itself.
In any case, you might need to keep a transactional log file and use it to make sure data is consistent between accesses. Your app should be able to recover from failures by itself. My opinion is that SQLite is probably the way to go: combined with an ORM solution like NHibernate, it's really simple and safe to use.
For Serialization you can use Generic methods
public static class GenericSerializer
{
public static string Serialize<T>(ICollection<T> listToSerialize)
{
MemoryStream stream = new MemoryStream();
XmlSerializer xmlSerializer;
try
{
xmlSerializer = new XmlSerializer(typeof(List<T>));
xmlSerializer.Serialize(stream, listToSerialize);
return Encoding.UTF8.GetString(stream.ToArray());
}
finally
{
stream.Close();
}
}
public static string Serialize<T>(T objectToSerialize)
{
MemoryStream stream = new MemoryStream();
XmlSerializer xmlSerializer;
try
{
xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(stream, objectToSerialize);
return Encoding.UTF8.GetString(stream.ToArray());
}
finally
{
stream.Close();
}
}
public static T Deserialize<T>(string xmlDataToeSerialize)
{
XmlSerializer xmlDeSerializer = new XmlSerializer(typeof(T));
StringReader stringReader = new StringReader(xmlDataToeSerialize);
return (T)xmlDeSerializer.Deserialize(stringReader);
}
}
For Update and Delete You can Retrieve the collection or object from file and edit and overwrite the existing one or you can use XPath expression for directly edit the XML
XML/0340_XPath.htm">http://www.java2s.com/Tutorial/CSharp/0540_XML/0340_XPath.htm

Serialize C# class directly to SQL server?

can anyone suggest the best way to serialize data (a class actually) to a DB?
I am using SQL server 2008 but i presume i need to serialize the class to a string / or other data type before storing in the database?
I presume that this field needs to be text or binary??
Does SQL server 2008 (or .net 3.5) support serializing directly tothe database ??
Any help really appreciated
You can xml serialize the class into an xml field. We use this all the time for exception logging in an ETL.
Using the XmlSerializer you may want a helper method somewhere which serializes the class to a string...
public static string SerializeToXml<T>(T value)
{
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, value);
return writer.ToString();
}
Then just put the string into the db like any other.
The best way to store data in a database is in columns (per property), so that it is queryable and indexable. ORM tools will help with this.
However, it is also possible to serialize a class as a CLOB/BLOB (varchar(max)/varbinary(max) etc).
It this is what you want, avoid anything implementation-specific or version-intolerant; so in particular, don't use BinaryFormatter. Anything contract-based should work; XmlSerializer, DataContractSerializer, etc. Or for fast binary, protobuf-net might be worth a look.
But I stress; columns would be better.
Without generics (better sollution)
public static string SerializeToXml(object value)
{
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
XmlSerializer serializer = new XmlSerializer(value.GetType());
serializer.Serialize(writer, value);
return writer.ToString();
}
I've serialized objects as XML and thrown those into the database just fine. Since we knew the max amount of text we used the varchar(max) datatype instead of getting into TEXT or Binary formats.
This was a OLTP web application and one thing we found was that using a column with an xml datatype invoked some significant cpu usage as the xml was validated on every insert. In our case the xml was never queried for anything so not having the xml query capabilities worked out ok for us.
There are couple of options:
Runtime serialization, serializable objects are marked with the
Serializable attribute, in which case the IFormatter class does all the work of
serialization. A serializable object can ISerializable, but then you will
need to implement the GetObjectData( ) method. The problem with runtime serialization is that program reading the xml data needs to have
the knowledge of the CLR types.
Xml serialization: Unline runtime serialization, you will get good interoperability in this case.
The XmlSerializer type contains the methods Serialize( ) and Deserialize( ), thus
any object can be serialized to XML and saved into the database and when you retreive it back, you
can deserialize it easily.
To read data from the database, you can use the SqlCommand class
method that executes SQL queries, namely ExecuteXmlReader( ).
ExecuteXmlReader( ) returns an instance of XmlReader and that will read your xml data.
Check out Linq-to-SQL (questions on SO, resource on MSDN) or other O-R Mapping options.

Categories