Question

I am working on a project and need help with regards to auto incrementing ID fields.

In terms of serialization, what is the best way to get the ID from when it was last serialized when it comes to deserialization of a static variable that you have been auto incrementing upon each instantiation of a class.

For instance...

[Serializable]
class Category
{
    private static int iCatID = 0;
    private int iCategoryID;
    private string sCategory;

    public Category(string _sCategory)
    {
        iCatID++;
        iCategoryID = iCatID;
        sCategory = _sCategory;
    }
}

I learnt the hard way that after creating 5 or so instances of this class, I serialized it, then deserialized and expected iCatID to pick up where it left off when I started creating more instances of the class, but it had of course reset back to 0.

What I want to know is how do I keep track of an auto incrementing variable in between serialization and deserialization and what would be best practice?

I've thought of two ways to possibly do it:

  1. When serializing the class, save the value of the static variable to a global setting and get that value again and set the static variable from the global setting on deserialization.
  2. When deserializing the class, use linq to query all instances of the class and get the highest number and then set the static variable accordingly.

I'm sure that there's a more elegant way of dealing with this.

Any help would be great, thanks.

Was it helpful?

Solution

Serialization is about instances... if you took a snapshot then it would be stored, i.e.

static int nextCatID;
private readonly int catID;
private string category;
...
public Category(string category)
{
    catID = Interlocked.Increment(ref nextCatID);
    this.category = category
}

here catID is the value related to the individual instance - and would be serialized and deserialized; of course, it could then lead to repeats: if you serialize item 1 and then deserialize it 5 times, you'll have 5 more "item 1"s.

If you wanted the value to be set during deserialization, you can do that too - just mark the field as non-serialized:

static int nextCatID;
[NonSerialized]
private int catID;

and set it in a post-serialization callback using the same code from the constructor (note that because the callback is not a constructor, you can't use readonly):

[OnDeserialized()]
private void OnDeserialized(StreamingContext context)
{
    catID = Interlocked.Increment(ref nextCatID);
}

OTHER TIPS

You could:

private static long iCatID = DateTime.Utc.Ticks;

start your counter with the current time (UTC) converted in a long. So at any run of your program with a little luck (if your user hasn't changed the clock), all the new IDs will be > all the old IDs.

Note that by using UTC you are resistant to changes of Summer Time/Winter Time.

Another solution is to simply forget about Id and use Guid.

You generate it through Guid.NewGuid() and it will be unique. The only problem is that you have just lost the ordering of items. You can't simply compare two Guid and tell "this is newer, this is older". You can tell that they are equal/different.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top