我试图在复杂类型上阅读msdn article。但它没有解释何时使用它。关于复杂类型以及何时使用它们的网络也没有全面的解释。
答案 0 :(得分:38)
冗长的解释是在你链接的MSDN文章中...所以你基本上想要一个简单的解释:
复杂类型是一组属性,它们存在于C#的自己的对象中,但是映射到现有表(包含它的实体的表)上的列,而不是拥有自己的表(这将是需要钥匙等。)。
所以想象一下你想在数据库上使用这个表:
Select Types (1,3,9)
Select ANum (0,5)
Type 1, Num 5 should be bigger than 10 In Val2
Type 1, Num 5, should be smaller than 30 In Val2
Type 3, Num 0, should be smaller than 8 In Val1
但是想在C#实体中使用这个结构:
SELECT analyse.* FROM analyse
INNER JOIN
(SELECT ID FROM analyse WHERE Type = 1 AND Num = 5 AND Val2 < 30 AND Val2 > 10) AS a1 ON a1.SID = analyse.SID
(SELECT SID FROM analyse WHERE Type = 3 AND Num = 0 AND Val1 > 8) AS a3 ON a2.SID = analyse.SID
WHERE Type IN (1,3,9) AND Num IN (0,5) ORDER BY ID, Type, Order, Num ASC
因此Orders
----------
Id (bigint)
Name (varchar)
Street (varchar)
Region (varchar)
Country (varchar)
将是一个复杂的类型:它本身不存在(在数据库中不会有class Order
{
long Id;
string Name;
struct Address
{
string Street;
string Region;
string Country;
}
}
表)...它只会作为一组存在Address
表上的列。
正如@HenkHolterman在评论中所指出的,具有复杂类型的价值是拥有一个C#实体,可以将其用作其他包含实体的值(在我的示例中,您可以使用Addresses
例如,Orders
实体,但它将被映射为Address
表中的一组列。它使得处理复杂类型中的值变得容易。
缺点恰恰在于:如果发生在不同实体之间可以共享相同的Supplier
(或您使用的任何其他类型),则可能必须在数据库中多次重复复杂类型值。
您选择使用复杂类型还是单独的实体取决于您和您的设计。
答案 1 :(得分:8)
考虑这个ContactDetails
类,例如:
public class ContactDetails
{
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
public string FaxNumber { get; set; }
}
默认情况下,EF会将ContactDetails
视为实体。这意味着如果(例如)您拥有导航属性为Person
类型的ContactDetails
类,则EF会将Person.ContactDetails
关系映射到其他表(因为实体具有自己的身份,因此其他实体可能会引用它 - 而这需要关系术语中的不同表格。)
通过将ContactDetails
表示为复杂类型,EF将不再将其视为需要关系的实体,而是将其映射到父级的同一个表(包含)实体(我的示例中为Person
),有效地使其成为Value Object。