Hi

I have two projects that use the same database to insert data. One is an MVC project, the other is a Functional Test Project. they both reference a third project just for my models. I use a dedicated key generated on one of the tables, if I insert a record into the table via the test project and do the same on the web project, I get a key violation exception, which means that both sessions are inserting the record with the same key. Is there any way to avoid key overlapping on different sessions created by different domains, even though the use the same configuration?

regards Jamal

asked Mar 26 '14 at 02:28

Jamal%20Lucas's gravatar image

Jamal Lucas
5556

Hello Jamal, could you provide your revelant persistent model parts? Code to create entity that causes this error would be useful as well!

(Mar 26 '14 at 03:28) Denis Krjuchkov Denis%20Krjuchkov's gravatar image

2 Answers:

Hello Jamal,

I think the problem is caused by starting two domains in the PerformSafely upgrade mode. In this mode DataObjects.Net will upgrade database schema as well as model metadata in the database. This is complex process and it should not be performed from different applications at the same time.

Also there is one more issue with your code:

Result of

session.Activate();

should be properly disposed by wrapping the call with the using operator for example. Otherwise you'll leak session object in a thread-static field.

So the question is Shouldn't each process receive a different set of keys to work with? How does DO handles key generation if more than one process is accessing the same database?

DataObjects.Net uses native sequence-generation facilities (e.g. sequences or tables with identity columns). However to optimize performance keys are fetched in groups (by default 128 elements each). It is a normal situation to have multiple processes using the same database. Just make sure they don't upgrade it simultaneously.

answered Mar 31 '14 at 03:17

Denis%20Krjuchkov's gravatar image

Denis Krjuchkov
179325

Thanks Denis, so you think that if I use Skip for the upgrade mode of the test project it should work?

(Mar 31 '14 at 07:19) Jamal Lucas Jamal%20Lucas's gravatar image

Skip means "Don't check database schema for validity". So it might or might not work depending on the actual DB. You need to decide who and when will upgrade your schema. For example it might be a dedicated unit-test or special application that you'll run or your main web application. The last option is not recommended for production, but OK for development (if every developer has it's own DB instance).

If you're looking for a recommended solution I think it's worth creating a separate application (console or GUI) that will perform DB maintenance operations.

(Mar 31 '14 at 07:41) Denis Krjuchkov Denis%20Krjuchkov's gravatar image

Hi Denis,

my model is something like this

[HierarchyRoot]
[KeyGenerator(KeyGeneratorKind.Default, Name = "UserGenerator")]
public class User : Entity
{
    [Field, Key]
    public long Id { get; private set; }

    [Field(Length = 100)]
    public string GivenName { get; set; }

    [Field(Length = 100)]
    public string FamilyName { get; set; }

    [Field]
    public DateTime? DateOfBirth { get; set; }
}

my web.config in the web project is

<Xtensive.Orm>
<domains>
  <domain name="Default"
          provider="sqlserver"
          connectionString="Data Source=localhost; Initial Catalog=DBTest;Integrated Security=True; MultipleActiveResultSets=true;">
    <types>
      <add assembly="Logic"/>
    </types>
  </domain>

and I build the domain using the code

var config = DomainConfiguration.Load("Default");
config.UpgradeMode = DomainUpgradeMode.Perform;

var domain = Domain.Build(config);

the functional test project has an app.config file with the same configuration for my domain

<Xtensive.Orm>
<domains>
  <domain name="Default"
          provider="sqlserver"
          connectionString="Data Source=localhost; Initial Catalog=DBTest;Integrated Security=True; MultipleActiveResultSets=true;">
    <types>
      <add assembly="Logic"/>
    </types>
  </domain>

and uses the same code above to build the domain. Then I run the web application with ctrl + F5 (Start without debugging) So I can have the process running. And run my test project to create a new user

using (var session = domain.OpenSession())
        {
            session.Activate();
            using (var tx = session.OpenTransaction())
            {
                var user = new User()
                {
                    GivenName = "foo",
                    FamilyName = "bar"
                };

                tx.Complete();

            }
        }

So at this stage I have two processes running and accessing the same database.

Now if I use my web project to create a user too, when I try to complete the transaction, it gives me an exception saying that A key violation occurred, so the session used by the web project tries to create a user with the same key as that created by the functional test.

So the question is Shouldn't each process receive a different set of keys to work with? How does DO handles key generation if more than one process is accessing the same database?

I've also noticed that at some point all the keyGeneration tables in my DB are cleaned. By profiling my DB I got lines like that DELETE FROM [dbo].[UserGenerator-Generator];

Is this normal?

regards,

Jamal

answered Mar 31 '14 at 02:43

Jamal%20Lucas's gravatar image

Jamal Lucas
5556

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×12
×2

Asked: Mar 26 '14 at 02:28

Seen: 3,002 times

Last updated: Mar 31 '14 at 07:41

powered by OSQA