Welcome, Guest. Please login or register.
March 28, 2024, 11:19:16 PM

Login with username, password and session length

Search:     Advanced search
we're back, baby
*
Home Help Search Login Register
f13.net  |  f13.net General Forums  |  The Gaming Graveyard  |  Game Design/Development  |  Topic: Yegolev Learns C# - was Your app's data 0 Members and 1 Guest are viewing this topic.
Pages: [1] 2 3 4 Go Down Print
Author Topic: Yegolev Learns C# - was Your app's data  (Read 31835 times)
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
on: November 14, 2008, 05:18:15 AM

As some of you know, I'm puttering with C#.  Currently I have a simple idea for an app that I can use to teach myself several things but I need some help with direction.

My app is a sort of recipe book, which I creatively titled RecipeBook.  Currently I have the easy bit working since I basically just used one of the examples from Head First C# to make a front end to a DB (MS SQL Server 2005) that contains recipe details.  Now I have hit a wall where I know what I want to do but not how to do it: I can flip through the book and presumably search for fields, but what I would like to do is specify an ingredient (row) and have it show me all of the recipes (columns) that use that.  At this point it should be obvious that I don't know the first thing about MSSQL, which is what I used here.  I was initially going to ask about a good book for raw beginners....

My problem-solving training kicked in and lead me to ask the question: how is data storage and retrieval normally done in game development?  I'm pretty sure it's not with a DB file.  Once I get the answer to that, I can then ask other questions.
« Last Edit: January 02, 2009, 11:18:04 AM by Yegolev »

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Trippy
Administrator
Posts: 23612


Reply #1 on: November 14, 2008, 05:33:50 AM

Need to see your DB schema.

However off the top of my head, for just the recipe part and ignoring a quantity column I would do something like this:

Table recipe
id: recipe id
name: recipe name

Table ingredients
id: ingredient
name: ingredient name

Table recipe_ingredients
id: whatever (or leave it out)
recipe_id: id from recipe table
ingredient_id: id from ingredient table

Then given an ingredient by name you would do

select recipe.name
from recipe_ingredients, ingredients, recipe
where ingredients.name = "<search name>"
and ingredients.id = recipe_ingredients.ingredient_id
and recipe.id = recipe_ingredients.recipe_id
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #2 on: November 14, 2008, 06:17:32 AM

Implicit joins make baby Jesus cry.

Code:
SELECT recipe.name
  FROM recipe R INNER JOIN recipe_ingredients RI ON RI.recipe_id = R.recipe_id
    INNER JOIN ingredients I ON I.ingredient_id = RI.ingredient_id
  WHERE I.name = '<input>'
Trippy
Administrator
Posts: 23612


Reply #3 on: November 14, 2008, 06:38:18 AM

Implicit joins make baby Jesus cry.
The JOIN keyword was added long after I learned SQL -- i.e. that's the way people were writing SQL long before you were born! awesome, for real
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #4 on: November 14, 2008, 07:15:56 AM

Ignorance of proper best current practices is no excuse. Oh ho ho ho. Reallllly?
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #5 on: November 14, 2008, 07:50:17 AM

You guys seem to feel it's OK for me to write a game with MS SQL, so next question: what is a good book for learning what the fuck you guys just wrote. awesome, for real I have done a few queries on the Oracle DBs at work but that's not nearly the same as setting up my own data layout and figuring out how to query it.

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #6 on: November 14, 2008, 08:22:48 AM

... fuck. I just deleted a huge post. Fuck you, funny mouse buttons.

I learned SQL back in the 90s by hacking out database-driven websites, using tutorials on the web. If you want to learn more about it, you can almost certainly Google up a few beginner guides to SQL - the basics don't change much between the various flavors of the language. Once you have a handle on how to store your data, get it out and arrange it in a manner useful to you, you can move on to architectural topics like database normalization.

That said, for game development, I think the answer is "it depends". MMORPGs almost universally use relational database systems - I'm aware of MMOs that use MSSQL, Oracle, and Postgresql. DAOC and some of the older games, if I remember right, faked a database and used structured files on disk/in memory instead; presumably, they had some proprietary layer that handled the ugly details of manipulating and querying that data.

For non-MMOs, it's going to depend on your game architecture. If you're building it in an object-oriented manner (and you probably are, if you're using C#) all your runtime data is likely to be governed by objects in memory - precisely how would be a discussion of design patterns and proper object-oriented design. There's roughly a hundred thousand books on those topics published every few days.

For your data on disk, well, I suppose that depends on what you're storing. Presumably you'd keep textures and models in an appropriate format that's exportable by your editing tools and readable by your engine. For static numerical or text data, you can probably just use CSV or tab-delimited text files. They're easy to edit in Excel and simple to parse. For crazy-ass binary data or complex data structures derived from your in-engine objects, you'll probably want to use an object serialization library. I found this when googling for "C# object serialization".

The TLDR is: It depends on what data you're storing, what your game is, and what your game's engine architecture likes/can handle.
Salamok
Terracotta Army
Posts: 2803


Reply #7 on: November 14, 2008, 09:58:31 AM

Need to see your DB schema.

However off the top of my head, for just the recipe part and ignoring a quantity column I would do something like this:

Table recipe
id: recipe id
name: recipe name

Table ingredients
id: ingredient
name: ingredient name

Table recipe_ingredients
id: whatever (or leave it out)
recipe_id: id from recipe table
ingredient_id: id from ingredient table

and this doesn't seem overnormalized to you for the task at hand?
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #8 on: November 14, 2008, 10:29:48 AM

Further thought on this leads me to think it might be easier by far to implement my data structures as C# collections of an appropriate type, at least the static ones.  Persistent data can be put into a CSV file, and this avoids me having to bother with how-to-read-a-dbf on machines without SQL Server 2005.  I will have to think about it more in terms of the game I want to write.

If you extend the idea of the RecipeBook to a game that heavily implements crafting, you can see where it would be a great idea to generate a list of recipes that use a particular material.  I would probably want to do this without using a .dbf file if I need to have a SQL service running to do it.  Decisions, decisions.  Will think on this more.

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #9 on: November 14, 2008, 11:14:12 AM

If your recipes are all pre-authored, you can generate a file that behaves like a cross-referencing table. It would be structured essentially identically to the relationship table Trippy posted above.

So, e.g., you would have 3 values per line, those being recipe identifier, material identifier, quantity. The naive way of querying this is to simply loop over every line, appending the recipe identifier to a list of recipe identifiers every time you came across a line with a matching material identifier. After that, it's simply a job of optimizing - for example, if you do this query a lot, you could construct a tree or hash table keyed off of the material identifier that gives you the list of recipe identifiers. You could do it up-front or construct it lazily as new material identifier searches are requested, and then caching the results.
Salamok
Terracotta Army
Posts: 2803


Reply #10 on: November 14, 2008, 11:59:13 AM

Most windows boxes should have MSDE loaded and I believe you can include it in your install package.  The entire point of MSDE is to provide a desktop based alternative to MS SQL Server, the theory being that you only need to change 1 or 2 lines of code to migrate your app from SQL Server to MSDE. 

Basically sounds like ODBC to me but I stopped using M$ development products before MSDE came out, so i couldn't tell you how well that works. 

Having nicely normalized tables is all fine and dandy but if you over do it you will see a noticable negative performance impact when retrieving a data set that requires an excessive number of joins.  For a prime example of this one only need to run a complex report or 2 in ACT and watch it grind away for several hours on a 10000 record database before spitting out it's report.

Anyhoo, Structure aside if you store your data in a way that will allow you to use SQL for data handling you will be saving yourself a fair bit of code work.
Tarami
Terracotta Army
Posts: 1980


Reply #11 on: November 14, 2008, 06:21:03 PM

I would avoid CSV - while it might be simple to imagine and plan, it's a complete bitch to maintain. You need very strong versioning because a single faulty value can screw up the entire data set.

XML queried with XPath (tutorial) could be a solution. It's quite verbose, but is instead very robust and easy to maintain even manually with a text editor (saves you having to write a tool early on). .NET has competent XPath support already in it, System.Xml.XPath.XPathDocument. It's pretty fast (it's memory-resident for the duration of the query), much faster than digging in a flat file would be.

Another option is querying XML with XLinq (System.Xml.Linq.XDocument), which is powerful also for creating and shaping XML documents. Google-fu will teach you how. smiley

As Yoru mentioned, binary serialization is yet another option. However, it'll get messy as it will not make a difference between an object reference which you want to serialize and one you don't (which can give you circular serialization, along with storing a lot of junk or directly corrupt data) unless you're being very conscious about adding the NonSerialized-attribute everywhere. There are simply no guarantees for what it will do to your objects when they get serialized and it will likely involve large amounts of debugging and trial&error. It's also very inconsistency prone due to this - if two objects reference the same object, they might serialize it differently because it has changed between the dumps. A huge thread-lock would solve that, but thread-locks are bad.

Since .NET is a managed environment, there's no easy way to just dump memory to disk - because the memory is never under your control and what exists at a location in it at one line of code might be gone the next. Usually it's better and far more controlled to deal with binary I/O using System.IO.BinaryWriter/Reader, but that means alot of typing of (de)serialization methods in the data classes.

As for memory-resident collections, I can only recommend System.Collections.Generic.Dictionary<TKey, TValue>, it's an implementation of System.Collections.HashTable and pretty much the fastest way in .NET to do random access in a collection.

Also, easily overlooked, don't forget that the absolutely fastest, no contest, way of traversing data is simply by creating the references needed from objects to the data they need to find.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #12 on: November 14, 2008, 06:32:20 PM

Hey, I understood almost all of that!  Except the last paragraph, which I have the odd feeling is something I really want to understand.

Tarami, since you haven't been playing Yegolev: The Home Game, I'll tell you up front that I have zero real programming experience.  I can do Korn and Perl but that's it.  I'm basically chewing my way through O'Reilly books to learn C#, which so far seems to sit between Perl and C in difficulty.  So if you start talking about heaps and pointers and what not, I might not get it.  I probably know what you mean by creating a reference to your data directly (in a generic dictionary, I guess?), but I would like a better explanation of the details in your last paragraph, please.

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Tarami
Terracotta Army
Posts: 1980


Reply #13 on: November 14, 2008, 06:57:36 PM

I'll try to explain, this is the most common way I deal with caching when I have multiple "tables" of correlating data.

Create a class for each table that can store one row of data (let's say Recipe and Ingredient). Recipe should have a list of all the IDs of Ingredients it needs.

Create a Dictionary<,> for each class you just wrote. Pick TKey (the type of the key, such as string, or int, or anything class/struct you like) according to what you want to search by in the specific Dictionary. For example, for a list of recipes, you might want to search by ID, so that would be TKey = int. The TValue is the class for the data you're going to store.

Fill all the dictionaries from your datastore, doing _dicRecipies.Add(recipeId, recipeObject) until they're all in.

Now all your data is memory-resident. Go back to your recipe class. Since you know you'll need to look-up all the ingredients for each recipe, you can add a List<Ingredient> to that class. The same goes for your Ingredient class - you can add a List<Recipe> to that class, to hold all the recipes that uses that ingredient.  By now, you got a possible cross-reference between Ingredient and Recipe (a one-to-many association (not a relation, that's different ;-), one recipe links to multiple ingredients, one ingredient to multiple recipes).

Go back to the method where you added all the Recipes and Ingredients.

The complex bit:
Loop over the whole dictionary holding the Recipes (this can be done with foreach(var item in dicRecipes) { ... }, where item will be end-up being a KeyValuePair<,> ), then search the dictionary over Ingredients for each Ingredient-ID you got in the Recipe. Add that Ingredient directly to your List<Ingredient>, so you got a true memory reference to the ingredient, instead of just an ID. At the same time, in that Ingredient, add the Recipe you're currently adding Ingredients to, to that Ingredient's Recipe list.

This will give you the result of two inter-linked, searchable dictionaries, where each entry knows all the references the other dictionary got to it. So getting all recipes for an ingredient would be as easy as:

List<Recipe> relatedRecipes = dicIngredients[theIngredientId].RecipeList;

or
 
List<Ingredient> neededIngredients = dicRecipes[theRecipeId].IngredientList;

It'll be one single search, regardless of which direction you want to page, once you got it all running.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Margalis
Terracotta Army
Posts: 12335


Reply #14 on: November 14, 2008, 09:00:50 PM

My problem-solving training kicked in and lead me to ask the question: how is data storage and retrieval normally done in game development? 

Some sort of text/script variant or roll-your-own binary.

vampirehipi23: I would enjoy a book written by a monkey and turned into a movie rather than this.
Viin
Terracotta Army
Posts: 6159


Reply #15 on: November 14, 2008, 10:22:48 PM

I just wanted to point out that a lot of games don't use the relational aspects of DBs, because it's too slow. They typically use a format that's very fast at lookups and searching, and use cross reference tables that are generated when data changes (sorta like Views but only created once). That's often why devs can't add more data to a window, because their "view" only pulls in certain fields from different tables.. they would have to rebuild that view (potentially gigs of data) to have access to more fields.

Granted, this might be old (I've been out of game dev circles since about 2000), but even today most fast transaction oriented DB implementations I've seen do not use any relational data structures if they can avoid it.

- Viin
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #16 on: November 15, 2008, 07:19:02 AM

This is excellent stuff, particularly Tarami's description.  Looks like the way to go is to use memory structures and if I want to persist something, I'll fabricate some simple text/binary dump.  I now have some more direction, too, which is awesome.  Tarami, I.O.U. One Beer.

1. Implement Tarami's idea, which looks like a totally awesome learning experience. I haven't done anything with dictionaries yet.
2. Work on writing out data to a file format of some sort. (thanks Margalis and Viin)
3. Look at how to add new ingredients and recipes via the GUI.

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Tarami
Terracotta Army
Posts: 1980


Reply #17 on: November 15, 2008, 01:12:24 PM

You're welcome. smiley Post or PM if you need help getting started with the writing/reading to/from disk. There's a dozen ways to do it, some better than others.

Oh, and breakpoints (for debugging) are your friends. Use them EVERYWHERE and step through the code with F10 (step over)/F11 (step into).

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Tarami
Terracotta Army
Posts: 1980


Reply #18 on: November 26, 2008, 04:24:51 PM

So, howza goin'? DRILLING AND MANLINESS

- I'm giving you this one for free.
- Nothing's free in the waterworld.
sidereal
Contributor
Posts: 1712


Reply #19 on: December 04, 2008, 09:53:53 PM

I'm a late-coming jerk, so ignore me if you're already halfway done.

I would strongly recommend using a free off-the-shelf persistence engine, because serializing data to disk on your own is fraught with problems and is an unnecessary reinvention of the wheel (unless you just want to learn how it works).

Specifically, I'd recommend Berkeley DB, which will manage persistence, transactional integrity (if you're multithreading), optimization, and so on.

Also, JetDB exists but I have little experience with that.

THIS IS THE MOST I HAVE EVERY WANTED TO GET IN TO A BETA
Tarami
Terracotta Army
Posts: 1980


Reply #20 on: December 05, 2008, 01:34:14 AM

I was under the impression that Yegolev both wanted to avoid external runtimes and learn how it was done. There's a gazillion ways to write data to disk that's safer than BinaryWriter, but none that's as hands-on. (Well, except fopen, fwrite tongue)

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #21 on: December 05, 2008, 01:45:06 AM

Real programmers write a program that controls a pair of robotic arms that hold bar magnets, and use THOSE to flip bits on a disk.
Tarami
Terracotta Army
Posts: 1980


Reply #22 on: December 05, 2008, 01:59:22 AM

Real programmers write a program that controls a pair of robotic arms that hold bar magnets, and use THOSE to flip bits on a disk.
But we aren't real prologammers, so we cheat.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
sidereal
Contributor
Posts: 1712


Reply #23 on: December 05, 2008, 09:02:54 AM

I was under the impression that Yegolev both wanted to avoid external runtimes and learn how it was done. There's a gazillion ways to write data to disk that's safer than BinaryWriter, but none that's as hands-on. (Well, except fopen, fwrite tongue)

If by runtime you mean a separate process, BerkeleyDB runs in your app process space.  It's just a library that handles all of the transaction and query goo for you.  As is Jet.

But yes, the best way to learn is to do.  If learning about the difference between row-level and table-level locking is what you're interested in.

THIS IS THE MOST I HAVE EVERY WANTED TO GET IN TO A BETA
Tarami
Terracotta Army
Posts: 1980


Reply #24 on: December 05, 2008, 10:42:05 AM

By "runtimes" I primarily mean libraries, but I guess it can encompass other kinds of extensions aswell. MS Jet is "okay", never used Berkeley so I can't say which one is a better DB host. I'm guessing Berkeley. That doesn't seem to have a .NET wrapper though, so in this case it might be disqualified.

Taking it a little bit out of context here, because I'm not sure what Yegolev is really looking for:
Don't get me wrong, relational DBs are great, transactional engines are great, but at the same time as they offer a ton of functionality, they also introduce a ton of cryptic behaviour that is specific to that engine. In the best of cases, a relational DB is just awesome because of the data transformation power it means, but I wouldn't say learning to use a DB is cake. It takes most people years just to get a decent grasp of one dialect of SQL and even when they do know it fairly well, it's nearly worthless in another engine.

If you don't know DB basics to begin with (but have a decent understanding of bits and bytes) and just want to store some data, I wouldn't want to impose the huge luggage of learning a DB engine. To a professional it's a no-brainer, but DBs also come with alot of weird restrictions (that adept users view as features) for reasons that are everything but clear. Mangling of some in-memory structures is much more straight-foward, I dare say.

I think for these reasons, XML is really the first thing I try to teach someone new to the whole data storage deal. It's structured, supports automatic (de)serialization well and it's just text that you can modify in an editor. Transactions and locks are usually requirements that come quite a way down the line. Beginners need to be pragmatic, or they'll drown in things they "need" to learn before they can even start doing what they wanted to do to begin with. Most people want to see some results, not necessarily do it "the right way".

Well, that's just my view on it.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #25 on: December 08, 2008, 12:05:50 PM

How's it going?  Slowly.  I had to switch gears back to Korn and rewrite a script that needed attention.  It now actually works in 99.999/100 cases (estimated Ohhhhh, I see.) rather than silent failures in certain places.  After that I ran into a situation in another Korn script which set off the Perl light, so I again shifted gears and spent some time recreating it in Perl.  Furthermore I had to remind myself of a bunch of Perl things, this time adventuring in filehandle input filters and the vagaries of system().  Now I'm hoping my mind shifts itself back to C# so I can actually implement a data structure as previously discussed.

What I am trying to achieve can be described in Tiers, I suppose.

Make A Game And Let People Play It (I'd rather not put MSSQL into the distro)
Make A Utility That I Use (same as above)
Write A Nontrivial And Original C# Program
Learn How To Program C#

There are multiple motivations at work here and I neither desire nor need a robust data persistence scheme other than regular files... not unless I decide I want to go multiuser but I'm not pretending I will be ready for that anytime soon.  I was thinking using a DB would be awesome, but I am quickly seeing that it is overkill for any of my goals, and perhaps even counter to the lowest Tier.  I'm definitely not afraid of making system calls, or calling methods in a non-managed DLL, I just don't know how yet. awesome, for real

Anyway, once I implement some sort of structure like Tarami outlined, I'll come back and share progress.

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Tarami
Terracotta Army
Posts: 1980


Reply #26 on: December 08, 2008, 01:47:59 PM

Don't worry about making going outside managed space, it's virtually impossible to do by mistake in .NET. The garbage collector and disposal routines will clean up pretty much any slop you leave, including open network streams and lingering file handles. It used to be sorta sensitive to that kind of abuse, but since 2.0 it's really robust. 99% of what you need either exists in the framework already or you can download a ready-made wrapper.

Although, if you really really want to, visit http://www.pinvoke.net/ for your reckless API fix. DRILLING AND MANLINESS

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Murgos
Terracotta Army
Posts: 7474


Reply #27 on: December 08, 2008, 02:10:32 PM


Anyway, once I implement some sort of structure like Tarami outlined, I'll come back and share progress..."I had to remind myself of a bunch of Perl things..."

If you are familiar with Perl then the structure that Tarami outlined should already be fairly familiar.

The Dictionary Object is a hash table, same as Perl hashes, that's been extended with a few features.  The custom classes he is referring to are just something to hold an Array or List.  Don't let the lexicon daunt you.

Hashes of array's (or hashes of hashes or arrays of hashes, etc...) are pretty common in Perl, and almost every other language, so if you haven't seen this sort of structure before this is something you will want to pay attention to and put in the extra effort for so as to be sure you get 'it'.

As an added tie in with what some of the above posters said, and for even more practice: once you have generated your hashes of objects with lists there is no reason to have to do that every time you run your program.  Use serialization to write them out to a file on exit and read them in (if they exist) on load.  If you have several thousand recipes, like my GF does, then it could save a good bit of time over reading from the DB and looping around to populate your hashes each time you run the program.  Rock Out

"You have all recieved youre last warning. I am in the process of currently tracking all of youre ips and pinging your home adressess. you should not have commencemed a war with me" - Aaron Rayburn
Yegolev
Moderator
Posts: 24440

2/10 WOULD NOT INGEST


WWW
Reply #28 on: December 09, 2008, 06:06:49 AM

If you are familiar with Perl then the structure that Tarami outlined should already be fairly familiar.

Actually, that's the biggest reason I got what he said.  I recognized the structure as cross-referenced hashes.  Probably my single biggest milestone in Perl was when I wrote a loop to slurp /etc/qconfig into an anon hash of hashes so I could pick out data at random, because that fucking rocked.  If I can translate that knowlege into C# then I'm halfway there.  Not in a Bon Jovi way.

As an added tie in with what some of the above posters said, and for even more practice: once you have generated your hashes of objects with lists there is no reason to have to do that every time you run your program.  Use serialization to write them out to a file on exit and read them in (if they exist) on load.  If you have several thousand recipes, like my GF does, then it could save a good bit of time over reading from the DB and looping around to populate your hashes each time you run the program.  Rock Out

This is a stellar idea and confirms my idea of avoiding a DB.  I feel ready!

Why am I homeless?  Why do all you motherfuckers need homes is the real question.
They called it The Prayer, its answer was law
Mommy come back 'cause the water's all gone
Tarami
Terracotta Army
Posts: 1980


Reply #29 on: December 11, 2008, 04:10:42 AM

Unfortunately it will not work. Serialization doesn't refresh memory references (for good reason).

Some code (image for easier reading):



C&P code here:

Sorry for SirBruce'ing it up like that. Point is, even if you serialize the dictionaries, you will have to manually rebuild both dictionaries, because they'll no longer be linked via shared references. Every item in each of them will have its own instance, which means you can't make a change that will affect both. Ergo, if you change something and re-serialize them, they will differ because the change won't "propagate" to the other dictionary.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Yoru
Moderator
Posts: 4615

the y master, king of bourbon


WWW
Reply #30 on: December 11, 2008, 08:31:31 AM

Dude, what IDE has a "copy for messageboard" command? DRILLING AND MANLINESS
Tarami
Terracotta Army
Posts: 1980


Reply #31 on: December 11, 2008, 08:44:29 AM

Dude, what IDE has a "copy for messageboard" command? DRILLING AND MANLINESS
It's a GIF. wink

Other than that, it's just Visual Studio, themed for undead.  ZombieSigne

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Murgos
Terracotta Army
Posts: 7474


Reply #32 on: December 11, 2008, 09:11:38 AM

Ok, so it might get a little more complicated.  Serialize out the data and not the dictionaries and rebuild the references when you read it back in.  It will still be a fun experiment.

Though, getting some RDB experience, enough so that "Select * from myTable where blah == blech" isn't something that gives you pause is pretty worth while too.
« Last Edit: December 11, 2008, 11:07:37 AM by Murgos »

"You have all recieved youre last warning. I am in the process of currently tracking all of youre ips and pinging your home adressess. you should not have commencemed a war with me" - Aaron Rayburn
sidereal
Contributor
Posts: 1712


Reply #33 on: December 11, 2008, 10:53:53 AM

Really, BerkeleyDB is perfectly setup for persistence like this. 

There are lots of ways of getting around the problem of deserializing constants.  One is to maintain a static pool of keys that deserialization pulls from.  (With Strings and Java, this is easily done with String.intern().  I'm sure there's a C# equivalent). 

Another is to just avoid dependence on key reference equality.  If your keys are any primitives or Strings, this is fine and probably good practice anyway.

THIS IS THE MOST I HAVE EVERY WANTED TO GET IN TO A BETA
Tarami
Terracotta Army
Posts: 1980


Reply #34 on: December 11, 2008, 11:32:47 AM

I used a string because it's a reference type and it served its purpose in an example. Typically you're not storing strings but your own types, which are not interned by the framework and thus you don't have an object repository unless you whip one up yourself. Which returns to the point I was arguing from the very beginning; serializing two key-unique lists and then building reference lists on load (or demand) is in almost every regard a better solution. Rolling your own serialization around something as structurally simple as a hashtable is quite a bit of work to no real end.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Pages: [1] 2 3 4 Go Up Print 
f13.net  |  f13.net General Forums  |  The Gaming Graveyard  |  Game Design/Development  |  Topic: Yegolev Learns C# - was Your app's data  
Jump to:  

Powered by SMF 1.1.10 | SMF © 2006-2009, Simple Machines LLC