我目前有2个模型需要运行迁移到新数据库中,而且我没有得到我期望的结构。如果这是一个简单的答案我很抱歉,我对Code First with Entity Framework相当新。
首先我有一个User
个对象。这只需要一个主键UserID
,然后填写一些字段。
public class User : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime Birthday { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public byte[] Picture { get; set; }
}
然后,我有一个Event
对象。这应该有一个EventID
作为主键,然后我尝试使用ForeignKey' d HostUser
,以及注册该事件的用户列表,存储在RegisteredUsers
表中。
public class Event : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EventID { get; set; }
[ForeignKey("HostUser")]
public int HostUserID { get; set; }
[ForeignKey("RegisteredUsers")]
public ICollection<int> RegisteredUserIDs { get; set; }
public virtual User HostUser { get; set; }
public string Description { get; set; }
public virtual ICollection<User> RegisteredUsers { get; set; }
}
基于此,我希望有一个包含User
和Event
表的数据库结构,在dbo.Event
到User
表中有一个外键列(对于外键的HostUserID),以及将用户列表映射到事件的查找表(对于RegisteredUsers列表)。
问题在于,当我根据此结构创建迁移时,我会为Up()
部分获取以下CreateTable方法。
public override void Up()
{
CreateTable(
"dbo.Event",
c => new
{
EventID = c.Int(nullable: false, identity: true),
HostUserID = c.Int(nullable: false),
Description = c.String(nullable: false),
NumberOfUsers = c.Int(nullable: false),
StartDate = c.DateTime(nullable: false),
EndDate = c.DateTime(),
CreatedAt = c.DateTimeOffset(precision: 7,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "CreatedAt")
},
}),
Deleted = c.Boolean(nullable: false,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Deleted")
},
}),
Id = c.String(
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Id")
},
}),
UpdatedAt = c.DateTimeOffset(precision: 7,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "UpdatedAt")
},
}),
Version = c.Binary(
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Version")
},
}),
})
.PrimaryKey(t => t.EventID)
.ForeignKey("dbo.User", t => t.HostUserID, cascadeDelete: true)
.Index(t => t.HostUserID);
CreateTable(
"dbo.User",
c => new
{
UserID = c.Int(nullable: false, identity: true),
Username = c.String(nullable: false),
Password = c.String(nullable: false),
Birthday = c.DateTime(nullable: false),
FirstName = c.String(nullable: false),
LastName = c.String(nullable: false),
EmailAddress = c.String(nullable: false),
Picture = c.Binary(),
CreatedAt = c.DateTimeOffset(precision: 7,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "CreatedAt")
},
}),
Deleted = c.Boolean(nullable: false,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Deleted")
},
}),
Id = c.String(
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Id")
},
}),
UpdatedAt = c.DateTimeOffset(precision: 7,
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "UpdatedAt")
},
}),
Version = c.Binary(
annotations: new Dictionary<string, AnnotationValues>
{
{
"ServiceTableColumn",
new AnnotationValues(oldValue: null, newValue: "Version")
},
}),
Event_EventID = c.Int(),
})
.PrimaryKey(t => t.UserID)
.ForeignKey("dbo.Event", t => t.Event_EventID)
.Index(t => t.Event_EventID);
}
最后两行是我想要关注的内容
.ForeignKey("dbo.Event", t => t.Event_EventID)
.Index(t => t.Event_EventID);
这是在User表上创建一个到事件表的ForeignKey,即使我没有在User模型的任何地方定义Event_EventID。我认为迁移假设用户一次只能注册一个事件,因为我没有看到任何类型的查找表来确定哪些用户注册了哪些事件。
我已经尝试弄乱我的Event
模型,将ForeignKey属性直接放在RegisteredUsers
对象上,并发现这个错误很快。
如何强制EF识别出我需要多对多的用户与事件关系?或者我在假设这个问题上咆哮错误的树?
修改
我删除了ForeignKey
属性并为每个属性设置了ICollection,我仍然有相同的错误,除了现在我有一个ADDITIONAL列,每个事件只允许一个用户,而没有EventUsers表。 / p>
public class User : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime Birthday { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public byte[] Picture { get; set; }
public virtual ICollection<Event> EventsRegisteredFor { get; set; }
}
public class Event : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EventID { get; set; }
public virtual User HostUser { get; set; }
public string Description { get; set; }
public virtual ICollection<User> RegisteredUsers { get; set; }
}
我最终得到了
CreateTable(
"dbo.Event",
c => new
{
EventID = c.Int(nullable: false, identity: true),
Description = c.String(nullable: false),
NumberOfUsers = c.Int(nullable: false),
StartDate = c.DateTime(nullable: false),
EndDate = c.DateTime(),
User_UserID = c.Int(),
HostUser_UserID = c.Int(nullable: false),
})
.PrimaryKey(t => t.EventID)
.ForeignKey("dbo.User", t => t.User_UserID)
.ForeignKey("dbo.User", t => t.HostUser_UserID, cascadeDelete: true)
.Index(t => t.User_UserID)
.Index(t => t.HostUser_UserID);
CreateTable(
"dbo.User",
c => new
{
UserID = c.Int(nullable: false, identity: true),
Username = c.String(nullable: false),
Password = c.String(nullable: false),
Birthday = c.DateTime(nullable: false),
FirstName = c.String(nullable: false),
LastName = c.String(nullable: false),
EmailAddress = c.String(nullable: false),
Picture = c.Binary(),
Event_EventID = c.Int(),
})
.PrimaryKey(t => t.UserID)
.ForeignKey("dbo.Event", t => t.Event_EventID)
.Index(t => t.Event_EventID);
编辑2 我仔细检查了我可以使用的最基本信息。
public class User : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public string Username { get; set; }
public virtual List<Event> Events { get; set; }
}
public class Event : CustomDataEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EventID { get; set; }
public virtual User HostUser { get; set; }
public virtual List<User> Users { get; set; }
}
但是,这个结构仍然没有给我必要的EventUsers或UserEvents表,它只是向数据库添加了一个允许单个UserID的列
public override void Up()
{
CreateTable(
"dbo.Event",
c => new
{
EventID = c.Int(nullable: false, identity: true),
User_UserID = c.Int(),
HostUser_UserID = c.Int(),
})
.PrimaryKey(t => t.EventID)
.ForeignKey("dbo.User", t => t.User_UserID)
.ForeignKey("dbo.User", t => t.HostUser_UserID)
.Index(t => t.User_UserID)
.Index(t => t.HostUser_UserID);
CreateTable(
"dbo.User",
c => new
{
UserID = c.Int(nullable: false, identity: true),
Username = c.String(),
Event_EventID = c.Int(),
})
.PrimaryKey(t => t.UserID)
.ForeignKey("dbo.Event", t => t.Event_EventID)
.Index(t => t.Event_EventID);
}
答案 0 :(得分:0)
对于多对多关系,只需在每个模型中添加一个集合:
用户模型中的添加:
public virtual ICollection Events {set;得到; } //多对多
并在事件模型中添加:
public virtual ICollection Users {set;得到; } //多对多
您不需要使用任何其他外键。
实体框架会自动创建EventUsers表,您无法从dbcontext访问此表。 (你不需要太多访问权限)
但是如果你想访问EventUsers Table,你应该删除用户和事件之间的多对多关系,创建一个新模型,例如EventUsers,并建立从用户到eventusers以及从event到eventuse的一对多关系。 / p>
答案 1 :(得分:0)
在多对多关系中,它将创建第三个表,其中包括两个表的主键,例如
public class User
{
[Key]
public int UserID { get; set; }
public string Username { get; set; }
public List<Event> Events { get; set; }
}
public class Event
{
[Key]
public int EventID { get; set; }
public List<User> Users { get; set; }
}
请注意,我在list
类中使用user
个事件,在event
类中使用相同的事件,这意味着用户可以拥有多个事件,而事件可以拥有多个用户({{1} })
因此,当我添加迁移时,它将创建第三个表名many to many
,其中包含两个表的外键。
修改强>
你已经使用了UserEvent
它创建了一对多的关系,所以你绑定只创建一个很多对很多的关系,所以不需要public virtual User HostUser { get; set; }