导航属性映射到一个实例var当成外键 [英] Map a navigation property to a instance var as Foreign key

查看:319
本文介绍了导航属性映射到一个实例var当成外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发一个实体框架代码优先(第4.4.0.0)与.net Framework 4.0中的C#库。

I'm developing an Entity Framework Code First (v. 4.4.0.0) C# library with .Net Framework 4.0.

我不知道如何设置零到一的关系。我的模型如下:

I don't know how to set zero-to-one relationship. My model is the following:

A 对话只能由一个用户创建( StarterUserId )。

A 对话只能有一个接收用户( RecepientUserId ),或者只有一组( RecipientGroupId )。

注意:这意味着, RecepientUserId 为空,如果 RecipientGroupId 不为null;或 RecepientUserId 不为空,如果 RecipientGroupId 为null。

A Talk can be created by only one user (StarterUserId).
A Talk can have only one recipient user (RecepientUserId) or only one group (RecipientGroupId).
Note: That means that RecepientUserId is null if RecipientGroupIdis not null; or RecepientUserId is not null if RecipientGroupIdis null.

A 用户可以是收件人零或n 六方会谈,但可以拥有零个或一个对话

A user can be a recipient of zero or n Talks, but a group can have zero or one Talk.

这是<强>对话类:

[DataContract]
public class Talk
{
    [DataMember]
    public int TalkId { get; set; }

    [DataMember]
    public int StarterUserId { get; set; }

    [DataMember]
    public int? RecipientUserId { get; set; }

    [DataMember]
    [ForeignKey("RecipientGroup")]
    public int? RecipientGroupId { get; set; }

    public DateTime DateUtcStarted { get; set; }

    [DataMember]
    public string DateStarted
    {
        get
        {
            return DateUtcStarted.ToString("dd/MM/yyyy HH:mm");
        }
        set
        {
            DateUtcStarted = DateTime.Parse(value);
        }
    }

    public User StarterUser { get; set; }
    public User RecipientUser { get; set; }

    public Group RecipientGroup { get; set; }
}

通过这种 TalkConfiguration 类:

class TalkConfiguration : EntityTypeConfiguration<Talk>
{
    public TalkConfiguration()
    {
        Property(t => t.StarterUserId).IsRequired();
        Property(t => t.RecipientUserId).IsOptional();
        Property(t => t.RecipientGroupId).IsOptional();
        Property(t => t.DateUtcStarted).IsRequired();

        Ignore(t => t.DateStarted);

        HasRequired(t => t.StarterUser).
            WithMany(u => u.TalksStarted).
            HasForeignKey(t => t.StarterUserId);
        HasOptional(t => t.RecipientUser).
            WithMany(u => u.InTalks).
            HasForeignKey(t => t.RecipientUserId);

        HasOptional(t => t.RecipientGroup).WithOptionalDependent(g => g.GroupTalk);
    }
}



这就是集团类:

[DataContract]
public class Group
{
    [DataMember]
    public int GroupId { get; set; }

    [ ... ]

    public Talk GroupTalk { get; set; }
}



以及 GroupConfiguration 类:

class GroupConfiguration : EntityTypeConfiguration<Group>
{
    public GroupConfiguration()
    {
        [ ... ] // Nothing related to GroupTalk
    }
}

使用这些类和配置我会在数据库中该对话表:

With these classes and configurations I get this Talk table at database:

我要让 Talk.RecipientGroupId FOREIGN KEY Group.GroupId 。但这种模式产生的另一列, Talk.RecipientGroup_GroupId FOREIGN KEY Group.GroupId 。而且,我不希望这样。

I want to make Talk.RecipientGroupId as a FOREIGN KEY to Group.GroupId. But this model creates another column, Talk.RecipientGroup_GroupId as FOREIGN KEY to Group.GroupId. And, I don't want that.

我该怎么办呢?

推荐答案

可选:可选一到一对一的关系被映射为独立的协会,而不是外键关联,这意味着你不能在你的模型类的外键属性。这就是为什么你不能链 HasForeignKey WithOptionalDependent 。而且我敢肯定,在 RecipientGroupId 会被忽略和EF认为<$ C $的 [ForeignKey的] 属性C> RecipientGroupId 与没有关系的目的一个普通的标量属性。

Optional:optional one-to-one relationships are mapped as independent associations, not as foreign key associations which means that you can't have a foreign key property in your model class. That's why you can't chain HasForeignKey after WithOptionalDependent. And I'm pretty sure that the [ForeignKey] attribute on RecipientGroupId is simply ignored and EF considers RecipientGroupId as an ordinary scalar property with no relationship purpose.

在数据库模式本身之间的关系有一个外键。这是您正在使用自动生成的默认名称眼看之一: RecipientGroup_GroupId 。但它不支持这种映射外键的属性。不过,我想你可以使用映射键

In the database schema itself the relationship has a foreign key. That's the one you are seeing with an autogenerated default name: RecipientGroup_GroupId. But it's not supported to map this foreign key to a property. However, I think you can rename the column using MapKey

HasOptional(t => t.RecipientGroup)
    .WithOptionalDependent(g => g.GroupTalk)
    .Map(m => m.MapKey("RecipientGroupId"));

如果你做,你的必须的删除 RecipientGroupId 对话类属性,否则EF会抱怨两种相互矛盾的列具有相同的名称。

If you do that you must remove the RecipientGroupId property from the Talk class, otherwise EF will complain about two conflicting columns with the same name.

我相信,可选:可选是唯一一个对一的关系,这是独立的协会,所有其他的都是那里的外键属性是在同一时间的主键属性外键关联(根据阿瑟·维克斯在的这个线程)。通过可选:可选的关系,这将是不可能的,因为主键属性不能为空的。

I believe, optional:optional are the only one-to-one relationships that are independent associations, all other are foreign key associations where the foreign key property is the primary key property at the same time (according to Arthur Vickers' answer at the bottom of this thread). With optional:optional relationships this would be impossible because a primary key property cannot be nullable.

由于您的 RecipientGroupId 有一个 [数据成员] 属性看起来要传递对一些服务边界值,因此需要外键作为某些原因属性值。在这种情况下,我会选择解决办法是映射谈话< - 基团关系,在<$ C $一个一对多的关系,要么没有导航属性在所有的C>组类或集合导航属性(带有参数的 WithMany()调用然后绘制它),然后确保业务逻辑该集合不能包含多个元素更多。

Since your RecipientGroupId has a [DataMember] attribute it looks that you want to transmit the value over some service boundary and therefore need the foreign key as property value for some reason. In this case the workaround that I would choose is mapping the Talk<->Group relationship as one-to-many relationship with either no navigation property in the Group class at all (mapping it with a parameterless WithMany() call then) or with a collection navigation property and ensure then in business logic that this collection cannot contain more than one element.

这篇关于导航属性映射到一个实例var当成外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆