這是我使用的解決方案的一個版本。我使用繼承層次而不是將屬性設置爲null來解決Ronnie在his answer中提出的問題,但它相當於同樣的事情。
以下是SQL:用戶有項目和集合,項目可以在集合中。
CREATE TABLE Users
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
name NVARCHAR (MAX) NULL,
email NVARCHAR (128) NULL,
PRIMARY KEY (id))
CREATE TABLE Items
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
userId UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR (MAX) NULL,
description NVARCHAR (MAX) NULL,
PRIMARY KEY (id),
FOREIGN KEY (userId) REFERENCES Users (id))
CREATE TABLE Collections
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
userId UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR (MAX) NULL,
layoutSettings NVARCHAR (MAX) NULL,
PRIMARY KEY (id),
FOREIGN KEY (userId) REFERENCES Users (id))
CREATE TABLE CollectedItems
(itemId UNIQUEIDENTIFIER NOT NULL,
collectionId UNIQUEIDENTIFIER NOT NULL,
PRIMARY KEY CLUSTERED (itemId, collectionId),
FOREIGN KEY (itemId) REFERENCES Items (id),
FOREIGN KEY (collectionId) REFERENCES Collections (id))
現在是數據模型類。爲了處理多重查詢的Dapper多重映射,集合比我期望的要複雜一些。
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public List<Item> Items { get; set; }
public List<Collection> Collections { get; set; }
}
public class Item
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class CoreCollection
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string Name { get; set; }
public string LayoutSettings { get; set; }
}
public class PartialDataCollection : CoreCollection
{
public Guid ItemId { get; set; }
}
public class Collection : CoreCollection
{
public List<Guid> ItemIds { get; set; }
}
public class CollectedItem
{
public Guid ItemId { get; set; }
public Guid CollectionId { get; set; }
public DateTime CreatedAt { get; set; }
}
最後我們有一個使用小巧玲瓏的多映射與多個查詢
控制器方法
[Route("GetUser/{id}")]
public User GetUser(Guid id)
{
var sql = @"SELECT * FROM Users WHERE id = @id
SELECT * FROM Items WHERE userId = @id
SELECT * FROM Collections
LEFT OUTER JOIN CollectedItems ON Collections.id = CollectedItems.collectionId
WHERE userId = @id";
using (var connection = new SqlConnection(ConnectionString))
{
var multi = connection.QueryMultiple(sql, new { id = id });
var user = multi.Read<User>().Single();
var items = multi.Read<Item>().ToList();
var partialDataCollections = multi.Read<PartialDataCollection, CollectedItem, PartialDataCollection>(AddCollectedItem, splitOn: "itemId").ToList();
user.Items = items;
user.Collections = partialDataCollections.GroupBy(
pdc => pdc.Id,
(key, group) => new Collection
{
Id = key,
UserId = group.First().UserId,
Name = group.First().Name,
LayoutSettings = group.First().LayoutSettings,
ItemIds = group.Select(groupMember => groupMember.ItemId).ToList()
}).ToList();
return user;
}
}
private PartialDataCollection AddCollectedItem(PartialDataCollection collection, CollectedItem collectedItem)
{
if (collection != null && collectedItem != null)
{
collection.ItemId = collectedItem.ItemId;
}
return collection;
}
如果羅尼是擔心在his answer設置person.Check = null
我擔心我的回答額外的複雜性,從加入類PartialDataCollection
到我的模型。但我看不到一個簡單的方法。
(注:我已經在GitHub上衣冠楚楚項目提出這個作爲an issue。)
+1,但它可能是值得*不*接受這個作爲答案,如果你正在尋找一個更好的方式來做到這一點,因爲沒有回答的問題似乎吸引了更多的關注。 – dumbledad
什麼是「CheckId」,你從哪裏得到? – dumbledad
明白了 - 這是[splitOn:](http://stackoverflow.com/a/7478958/575530)參數 – dumbledad