[英]Entity-Framework: Create Many-To-Many-Relations
We are using the "DB-First" approach for an application, cause the Database is shared between various applications, so it should be the "master". 我们对应用程序使用“ DB-First”方法,因为数据库在各种应用程序之间共享,所以它应该是“主数据库”。 (MySQL) (MySQL的)
We have 3 simple tables, responsible for the Role-To-Permission Assignment, like this: 我们有3个简单的表,负责角色到权限的分配,如下所示:
The Visual-Studio Model Designer (after building the model from the database) perfectly fine recocnices this as a "Many-To-Many" relation, not even generating a "Role_to_permission"-Entity, as there are no further attributes on the assignment) Visual-Studio模型设计器(从数据库中构建模型之后)可以很好地将其识别为“多对多”关系,甚至不会生成“ Role_to_permission” -Entity,因为分配没有其他属性)
Until now, we created those entries in the database, which lead to the expected outcome within the application. 到目前为止,我们已经在数据库中创建了这些条目,这些条目导致了应用程序内的预期结果。 (Accessing mappings) (访问映射)
Currently we are working on an Interface, allowing to assign "Permissions" to "Roles". 当前,我们正在开发接口,允许将“权限”分配给“角色”。 And here, I'm a little stuck: 在这里,我有点卡住了:
required
or a date
), the EMF creates an own entity for the relation - let's assume Permission_To_Role
. 如果这样的关系具有另一个属性(例如required
或date
),则EMF会为该关系创建一个自己的实体-让我们假设Permission_To_Role
。 then, I can "easily" create a relation, with the following code: 然后,我可以使用以下代码“轻松”创建关系:
using (MyDb db = new MyDB()){
Permission_To_Role ptr = new Permission_To_Role();
ptr.PermissionId = 5;
ptr.RoleId = 8;
ptr.CreationDate = DateTime.Now();
db.Permission_To_Role.Add(ptr);
db.SaveChanges();
}
Whatsoever - in this case - we don't have any additional attribute on the mapping, so the additional class is avoided by the EF Framework. 无论如何-在这种情况下-映射上没有任何其他属性,因此EF Framework 避免了其他类。
Im now trying hard to create a relation, but without success: 我现在正在努力建立关系,但没有成功:
using (MyDB db = new MyDB())
{
//Get ids.
long permissionId = 2;
long roleID = 5;
Permission p = db.Permission.Find(permissionId);
Role r = db.Role.Find(roleID);
r.Permissions.Add(p);
db.SaveChanges();
}
This always results in an Exception, and I can't figure out why (IDs are existing and correct) ... 这总是导致异常,我不知道为什么(ID存在并且正确)...
Exception of db.SaveChanges()
: db.SaveChanges()
异常:
An exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll but was not handled in user code EntityFramework.dll中发生类型为'System.Data.Entity.Infrastructure.DbUpdateException'的异常,但未在用户代码中处理
Additional information: An error occurred while saving entities that do not expose foreign key properties for their relationships. 附加信息:保存不公开外键属性为其关系的实体时发生错误。 The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源。 Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. 通过在实体类型中公开外键属性,可以简化保存时的异常处理。 See the InnerException for details. 有关详细信息,请参见InnerException。
Inner Exception: 内部异常:
An error occurred while updating the entries. 更新条目时发生错误。 See the inner exception for details. 有关详细信息,请参见内部异常。
Inner Inner Exception: 内部内部异常:
You have an error in your SQL syntax; 您的SQL语法有误; check the manual that corresponds to your MySQL server version for the right syntax to use near '(SELECT
Permission_to_Role
.PermissionId
,Permission_to_Role
.RoleId
FROM' at line 1 检查对应于你的MySQL服务器版本使用附近的正确语法手册“(SELECTPermission_to_Role
。PermissionId
,Permission_to_Role
。RoleId
FROM”在1号线
Ideas? 想法?
SHOW CREATE TABLE Permission_to_Role;
output: 输出:
CREATE TABLE `Permission_to_Role` (
`PermissionId` bigint(19) NOT NULL,
`RoleId` bigint(19) NOT NULL,
UNIQUE KEY `Permission_to_Role_unique` (`PermissionId`,`RoleId`),
KEY `Permission_Mapping_idx` (`PermissionId`),
KEY `Role_Mapping_idx` (`RoleId`),
CONSTRAINT `Permission_Mapping` FOREIGN KEY (`PermissionId`) REFERENCES `permission` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `Role_Mapping` FOREIGN KEY (`RoleId`) REFERENCES `role` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
As of the current comments: I enabled the output for queries generated by the EF, and found this charm - which is obviously a malformated Query: 截至当前评论:我为EF生成的查询启用了输出,并发现了这种魅力-显然是格式错误的查询:
INSERT INTO
(SELECT
Permission_to_Role.PermissionId,
Permission_to_Role.RoleId
FROM
Permission_to_Role AS Permission_to_Role
)
( PermissionId, RoleId) VALUES ( 2, 1)
The query actual should be: 实际查询应为:
INSERT INTO
Permission_To_Role
( PermissionId, RoleId) VALUES ( 2, 1)
So, I think this looks like a "bug"? 所以,我认为这看起来像个“虫子”? As mentioned above: 正如刚才提到的:
Whatsoever - in this case - we don't have any additional attribute on the mapping, so the additional class is avoided by the EF Framework. 无论如何-在这种情况下-映射上没有任何其他属性,因此EF Framework 避免了其他类。
there is no intermediate Permission_To_Role
Entity, hence it seems like EF is trying to replace this table name with the query 没有中间的Permission_To_Role
实体,因此似乎EF尝试用查询替换该表名
SELECT
Permission_to_Role.PermissionId,
Permission_to_Role.RoleId
FROM
Permission_to_Role AS Permission_to_Role
EVEN upon inserts... (Maybe this works for MsSQL and is a bad implementation for the MySQL Connector?) 甚至在插入时...(也许这适用于MsSQL,并且对于MySQL Connector是错误的实现?)
I'd really like to figure out the "cause" of this issue - but for now, I added another column grantedById
(referencing user.id
) to that relation table. 我真的很想弄清楚这个问题的“原因”,但现在,我在该关系表中添加了另一列grantedById
(引用user.id
)。
So, this caused the intermediate entity Permission_To_Role
to be generated in the Model, and made me believe it's going to work now! 因此,这导致在模型中生成中间实体Permission_To_Role
,并让我相信它现在可以正常工作! (Cause done that hundreds of times, like this: ) (原因是执行了数百次,如下所示:)
using (MyDb db = new MyDB()){
Permission_To_Role ptr = new Permission_To_Role();
ptr.PermissionId = 5;
ptr.RoleId = 8;
ptr.GrantedById = Session.CurrentUser.Id;
db.Permission_To_Role.Add(ptr);
db.SaveChanges();
}
But It should be possible to do Database-Inserts for Many-To-Many-Mappings
with 2 Foreign-Key-Constraint Columns
ONLY as well, shouldn't it? 但是,也应该只对带有2个Foreign-Key-Constraint Columns
Many-To-Many-Mappings
进行数据库插入,不是吗?
I'm a little tired right now, but finally got it to work. 我现在有点累,但是终于开始工作了。
I'm not 100% sure to outline the real problem, cause I changed a lot of things - but the following "findings" are kind of milestones while resolving this problem: 我不是100%肯定会概述真正的问题,因为我做了很多更改-但是以下“发现”是解决此问题时的里程碑:
I tried to add more columns as mentioned above, which did nor work out. 如上所述,我尝试添加更多列,但没有成功。 It caused the Mapping-Table to be present as entity, but the insert showed the same problem. 这导致Mapping-Table作为实体出现,但是插入内容显示了相同的问题。 (Insert Query, containing wired "SELECT" Statement instead of table name) (插入查询,包含有线的“ SELECT”语句而不是表名)
I noted, that the generated Mapping-Table (In EM-Designer) took ALL columns into account for the primary key , while I designed the table without any (composite) Primary Key in the MySQL-Designer (only a unique key was setup accross all columns): 我注意到,生成的映射表(在EM-Designer中)考虑了所有列作为主键 , 而我在MySQL-Designer中设计了没有任何(复合)主键的表 (只有一个唯一的键被安装了)所有列):
I was like f*** y** - and added a surrogate Primary Key-Column to the mapping-table (In the database designer)... 我就像f *** y **-并在映射表中添加了代理主键列(在数据库设计器中)...
and unchecked any Primary-Key-Membership in the EF-Designer for any remaining column: 并取消选中EF-Designer中任何剩余列的主键成员资格:
And guess what? 你猜怎么着? It works :-) 有用 :-)
using (MyDb db = new MyDB()){
Permission_to_Role ptr = new Permission_to_Role();
ptr.PermissionId = permissionId;
ptr.RoleId = r.Id;
ptr.GrantedById = u.Id;
ptr.GrantedAt = DateTime.Now;
db.Permission_to_Role.Add(ptr);
db.SaveChanges();
}
So, there are three things left to say: 因此,还有三件事要说:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.