Hi,

Anybody using composite primary keys with DataObjects.NET? I am unable to find sample for how to create class with composite primary keys.

If you have experience or idea, please let me know.

Cheers! Alex Ko Aung


Updated at 06.07.2010 8:51:40

Hi,

I simple modified sample codes in DO4.2 document as below and run.

[HierarchyRoot] 
public class WebPage : Entity 
{ 
  [Key(Position=0), Field] 
  public int Id { get; private set; }

  [Key(Position=1), Field]
  public string PageKey { get; set; } // I want to set PageKey value manually. That's why I remove private.

  [Field(Length = 200)] 
  public string Title { get; set; }

  [Field(Length = 200)] 
  public string Url { get; set; } 
}

I got error at below line. var config = new DomainConfiguration("postgresql://postgres:postgres@localhost:5432/do40test?Encoding=ASCII"); config.UpgradeMode = DomainUpgradeMode.Recreate; config.Types.Register(typeof(User).Assembly, typeof(User).Namespace); var domain = Domain.Build(config); // ERROR @: Default generator can serve hierarchy with exactly one key field.

What did I do wrong? My intention is that I want 2 primary keys in WebPage. But I want to set value manually into PageKey field.

Cheers! Ko Aung

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by aungzinko.

asked Jul 02 '10 at 02:02

Editor's gravatar image

Editor
46156156157


One Answer:

psulek wrote:

Hi, Anybody using composite primary keys with DataObjects.NET? I am unable to find sample for how to create class with composite primary keys. If you have experience or idea, please let me know. Cheers! Alex Ko Aung

Have you tried mark properties with attribute [Key] and its property "Position" ? (like [Key(Position = 0)]. Sample:

class MyEntity
{
   [Key(Position=0)]
   public int Key1 {get;set;}

   [Key(Position=1)]
   public int Key2 {get;set;}
}

I i understand manual than this is how to make composite primary keys in DO4.


Alex (Xtensive) wrote:

Also note that Entity.Key describes any key type. I.e. you can use this code also for entities with composite keys:

var key = entityWithCompositeKey.Key;
Console.WriteLine("Key: {0}", key); // We almost always implement ToString(); [DebuggerDisplay] is also frequently applied

// Key can be serialized to string
var keyAsString = key.Format();
var deserializedKey = Key.Parse(keyAsString); // Relies on Domain.Demand(), see the description of this method
Assert.AreEqual(key, deserializedKey);

// Resolving entity by its key
var theSameEntity = Qyery.Single(deserializedKey);
Assert.AreSame(entityWithCompositeKey, theSameEntity);

Alex (Xtensive) wrote:

Few more examples:

// Getting entity with composite key
var entity1 = Query.Single<MyEntity>(1,2,"X");

// The same code, but by explicitly creating composite key
var key = Key.Create<MyEntity>(1,2,"X");
var entity2 = Query.Single<MyEntity>(key);

psulek wrote:

Peter, thanks again :) You can also write simply [Key(1)] (there is a constructor accepting Position argument).

You're welcome, Alex.

Btw i could not find how to build composite primary keys in latest manual (checked only PDF version which is installed with DO4.3 RC4).


Alex (Xtensive) wrote:

Two facts:

  • DO4 doesn't allow you to change entity key after the construction of entity.

  • You can explicitly specify entity key on creation using appropriate Entity constructor: Entity..ctor(params object[] keyComponents).

If you need to change the key of already created entity, the only way to do this is to remove and create it again - with the new key.


Alex (Xtensive) wrote:

Err... This isn't related to database at all.

You should:

  • Add "private" keyword to PageKey setter

  • Add a constructor allowing to specify composite key values explicitly.

So final code must look like:

[Serializable]
[HierarchyRoot]
public class WebPage : Entity 
{ 
  [Key(Position=0), Field] 
  public int Id { get; private set; }

  [Key(Position=1), Field]
  public string PageKey { get; private set; }

  [Field(Length = 200)] 
  public string Title { get; set; }

  [Field(Length = 200)] 
  public string Url { get; set; }

  public WebPage(int id, string pageKey)
    : base(id, pageKey) // this call sets Key explicitly
  {
    // ... Key is already set here
  }
}

Btw, as I suspect, a part of key (Id) must be assigned automatically in this case. So the solution here is:

[Serializable]
[HierarchyRoot]
internal class IntKeyed : Entity 
{
  [Key, Field] 
  public int Id { get; private set; } 
}

[Serializable]
[HierarchyRoot]
public class WebPage : Entity 
{ 
  [Key(Position=0), Field] 
  public int Id { get; private set; }

  [Key(Position=1), Field]
  public string PageKey { get; private set; }

  [Field(Length = 200)] 
  public string Title { get; set; }

  [Field(Length = 200)] 
  public string Url { get; set; }

  public WebPage(string pageKey)
    : base(Key.Create<IntKeyed>().Value.GetValue<int>(0), pageKey) // this call sets Key explicitly
  {
    // ... Key is already set here
  }
}

answered Jul 02 '10 at 06:14

Editor's gravatar image

Editor
46156156157

aungzinko wrote: Hi,

Thanks for your reply. I haven't try yet. Let me try.

Cheers!

(Jul 02 '10 at 06:14) Editor Editor's gravatar image

Peter, thanks again :)

You can also write simply [Key(1)] (there is a constructor accepting Position argument).

(Jul 02 '10 at 06:14) Alex Yakunin Alex%20Yakunin's gravatar image

aungzinko wrote: Thank you Alex for your good examples....

Cheers!

(Jul 02 '10 at 06:14) Editor Editor's gravatar image

Concerning non-changing keys: of course, this is reasonable. I'll explain this a bit later.

(Jul 02 '10 at 06:14) Alex Yakunin Alex%20Yakunin's gravatar image

aungzinko wrote: Thanks for your reply. I don't know how to create again. But I drop database and create new fresh database does not work. I got same error.

I am expecting your detail explanation later.

Cheers!

(Jul 02 '10 at 06:14) Editor Editor's gravatar image
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

powered by OSQA