tags:

views:

16

answers:

1

I'm storing an IUser object in a Db4o database as follows (client is an IObjectClient):

public Guid AddUser(IUser user)
{
    lock (userLock)
    {
        user.Id = Guid.NewGuid();
        client.Store(user);
        client.Commit();
    }
    return user.Id;
}

The implementation of IUser that is used here has the field that is discribed in IUser IEnumerable<Roles> Roles { get;} implemented with a backing field IList<Roles> = new List<Roles>()

When I run the following UnitTest everything works fine:

[TestMethod]
public void UserStaysInRoleAfterServerRestart()
{
    string filePath = IOHelper.MakeAbsolute(ConfigurationManager.AppSettings["userRepository.path.db4o"] + "1");
    IUser expected = GenerateTestUser();
    expected.AddRole(Roles.Anonymous);
    IObjectServer userServer1 = Db4oFactory.OpenServer(filePath, 0);
    IUserRepository repo = new UserRepository(userServer1);
    repo.AddUser(expected);
    userServer1.Close();

    IObjectServer userServer2 = Db4oFactory.OpenServer(filePath, 0);
    IUserRepository repo2 = new UserRepository(userServer2);
    IUser actual = repo2.GetUser(expected.Id);
    Assert.IsTrue(actual.IsInRole(Roles.Anonymous));
}

When I use the same methods (AddUser and GetUser) in my website, separated by a "restart debugging" however, the GetUser() returns the IUser correctly, but with the Roles.Count() == 0

+1  A: 

Hi

One issue could be the update-deph. In your test, you use a new created IUser and use .AddRole() on it. So everything works fine. However, as soon as you call .AddRole() on an existing IUser the update-deph is relevant.
By default only the object passed to IObjectContainer.Store() are updated. All the object referenced are not updated. Since a list is also an object, it isn't updated. Therefore you have this possibilities:

If that isn't the issue, tell me and I'll remove this answer.

By the way. I the db4o-version you're using (7.4) has a suboptimal Guid-Handling. Maybe you should consider the newer version, 7.12.

Gamlor
I will check out the update depth, but I thought that creating a new server and client would ensure me I'm not running on cache but on actually retrieving the objects from file. Is there a way to circumvent the caching so I know for sure everything is correctly persisted?
borisCallens
I tried v7.12 but I ran in all sorts of crazy binding problems in my unit tests. All my tests failed on filenotfound exceptions which obligated me to start adding keys in the registry to have binding logging, then digging through these logs and manually copy-pasting the missing libraries to my unit test's bin folder. All the tests ran find before, so I decided to wait for a future stable release as I haven't ran into issues with the current one that are worth the bother yet.
borisCallens
The problem I was talking about would be in the first part of your test. There you create IUser, add a role to it and store it. This works fine. However, when you create you user first, store it, retrieve it later, add the role and store again, then the update-depth gets relevant. If it's to low, it won't work. And no, you cannot circumvent the ObjectContainer-Cache. This cache is essential for the db4o. (It's a bit like a Hibernate-session or LINQ to SQL-context).
Gamlor
Version 7.4 to 7.12 migration: Yeah another time.
Gamlor
aha! Indeed, in my website I'm essentially first creating and saving the user, then adding the role and saving it again (= updating). Thanks :D
borisCallens