Reputation: 1577
In my ServiceStack app I'm implementing a simple chat where 2 users can have a dialogue. For simplicity, I've just created a TextMessages table, which contains the following Fields:
public class TextMessage
{
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
[References(typeof(MyUserAuth))]
public int FromUserId { get; set; }
[References(typeof(MyUserAuth))]
public int ToUserId { get; set; }
[Reference]
[ForeignKey(typeof(MyUserAuth))]
public MyUserAuth FromUser { get; set; }
[Reference]
[ForeignKey(typeof(MyUserAuth))]
public MyUserAuth ToUser { get; set; }
//TimeZoneInfo.ConvertTimeToUtc(dateNow);
public DateTime UtcReceivedOn { get; set; }
public string Text { get; set; }
}
My UserAuth inherits the base one and adds 2 more fields:
public class MyUserAuth : UserAuth
{
public List<TextMessage> TextMessagesAsAuthor { get; set; }
public List<TextMessage> TextMessagesAsRecipient { get; set; }
}
Now let's say I create some users and then some messages:
var msg1 = new TextMessage { FromUserId = 1, ToUserId = 2, UtcReceivedOn = dt, Text = "Hello" };
var msg2 = new TextMessage { FromUserId = 1, ToUserId = 3, UtcReceivedOn = dt, Text = "Hello" };
var msg3 = new TextMessage { FromUserId = 1, ToUserId = 4, UtcReceivedOn = dt, Text = "Hello" };
var msg4 = new TextMessage { FromUserId = 1, ToUserId = 4, UtcReceivedOn = dt, Text = "Hello" };
And then I try to read my user:
var user = db.LoadSingleById<MyUserAuth>(1);
The problem here is that the user has 4 messages in both TextMessagesAsAuthor
and TextMessagesAsRecipient
while logically there should be 4 in TextMessagesAsAuthor
and 0 in TextMessagesAsRecipient
. How can i tell OrmLite to differ these two properties?
Upvotes: 3
Views: 657
Reputation: 143409
OrmLite only supports multiple 1:1 Self References as you're using in your TextMessage
table, it doesn't support multiple 1:M external references like you're trying to declare on:
public class MyUserAuth : UserAuth
{
public List<TextMessage> TextMessagesAsAuthor { get; set; }
public List<TextMessage> TextMessagesAsRecipient { get; set; }
}
Also note complex properties that don't have
[Reference]
attributes are blobbed with the row they're on, which isn't what you want here.
Also OrmLite's POCO References only load 1-level deep, i.e. references do not recursively go down and load the referenced table references as well or populate any cyclical back references which is what it looks like you're trying to do.
So I'd keep the text messages as they are:
var msgs = new[]
{
new TextMessage { FromUserId = 1, ToUserId = 2, Text = "msg #1" },
new TextMessage { FromUserId = 1, ToUserId = 3, Text = "msg #2" },
new TextMessage { FromUserId = 1, ToUserId = 4, Text = "msg #3" },
new TextMessage { FromUserId = 1, ToUserId = 4, Text = "msg #4" },
};
db.InsertAll(msgs);
Which you can use to Load their multiple self User references, e.g:
var msg1 = db.LoadSingleById<TextMessage>(1);
msg1.PrintDump(); //prints populated FromUser/ToUser properties
But you wont be able to do the same for MyUserAuth
multiple 1:M external references. In this case I would still add the TextMessage
collections to the MyUserAuth
table but you'll want to tell OrmLite to ignore them when creating the MyUserAuth
table which you can do with the [Ignore]
attribute, e.g:
public class MyUserAuth : UserAuth
{
[Ignore]
public List<TextMessage> TextMessagesAsAuthor { get; set; }
[Ignore]
public List<TextMessage> TextMessagesAsRecipient { get; set; }
}
Which you can then populate them manually, i.e:
var user1 = db.SingleById<MyUserAuth>(1);
user1.TextMessagesAsAuthor = db.Select<TextMessage>(x => x.FromUserId == 1);
user1.TextMessagesAsRecipient = db.Select<TextMessage>(x => x.ToUserId == 1);
user1.PrintDump(); //prints populated MyUserAuth TextMessages
Upvotes: 6