我很讨厌Entity Framework。它应该更容易,更快捷,但是太可怕了。
我正在对两个非常简单的表使用数据库优先方法。带有User
和Id
的{{1}}表,位于Username
上的主键和自动增量,以及带有Id
和{{1}的Permission
表},两列的主键以及从permissionname
到userid
的关系。
这是我授予和撤消权限的代码:
userid
user.id
属性绑定到一个复选框。
public bool ContributionMarginCustomer
{
get => GetPermission(_contributionmarginCustomer);
set => SetPermission(value, _contributionmarginCustomer);
}
授予权限非常有用。
使用ContributionMarginCustomer
删除权限会将其从数据库中的每个用户中删除。
我不了解这种行为。你们有吗?
谢谢
编辑: 方便用户
之前的权限表:
使用userId 15和键private void SetPermission(bool permissionIsGranted, string key)
{
var permissionStatus = permissionIsGranted ? PermissionStatus.Granted : PermissionStatus.Revoked;
using (var entity = new KundeninfoEntities())
{
var user = entity.Users.Single(x => x.Id == _user.Id);
var existingPermission = user.Permissions.SingleOrDefault(x => x.Name == key);
switch (permissionStatus)
{
case PermissionStatus.Granted:
if (existingPermission == null)
{
user.Permissions.Add(new Permission { Name = key });
entity.SaveChanges();
}
break;
case PermissionStatus.Revoked:
if (existingPermission != null)
{
entity.Permissions.Remove(existingPermission);
entity.SaveChanges();
}
break;
}
_permissions = entity.Permissions
.Where(x => x.UserId == _user.Id)
.ToList();
}
}
删除它后的权限表
编辑2:解决方案
我将权限表更改为仅一列作为主键。 这意味着新的权限表具有三列:Id(自动增量),Name和UserId,具有唯一的name和userid键。
上面的代码现在可以工作了,但是我对此并不满意。
答案 0 :(得分:2)
在第二种情况下,您不是从用户中删除许可,而是从实体(基本上是整个用户列表)中删除许可。 更改为
case PermissionStatus.Revoked:
if (existingPermission != null)
{
user.Permissions.Remove(existingPermission);
entity.SaveChanges();
}
break;
答案 1 :(得分:1)
将权限的状态设置为“已删除”。
var existingPermission = user.Permissions.SingleOrDefault(x => x.Name == key);
//your other code here.
entity.Entry(existingPermission).State = EntityState.Removed;
entity.SaveChanges();
答案 2 :(得分:1)
在我看来,您的数据库不够规范。恕我直言,这会使您的代码更加困难,并在授予/拒绝权限时引起问题。
您有Users
和Permissions
。每个User
都有零个或多个Permissions
,每个Permission
被授予零个或多个Users
。标准的多对多关系。
实体框架中的多对多设计如下:
class User
{
public int Id {get; set;}
// every user has zero or more Permissions (many-to-many)
public virtual ICollection<Permission> Permissions {get; set;}
...
}
class Permission
{
public int Id {get; set;}
// every Permission is granted to zero or more Users (many-to-many)
public virtual ICollection<User> Users {get; set;}
...
}
class MyDbContext : DbContext
{
public DbSet<User> Users {get; set;}
public DbSet<Permission> Permissions {get; set;}
}
这是实体框架所需要知道的,您设计了多对多关系。它将创建“用户和权限”表,并将创建(组)联接所需的联结表,当您要检索“授予用户的许可”或“具有某些许可的用户”时,需要完成此联接表
但是,您没有在代码中使用此联结表,而是使用ICollection
。实体框架足够聪明,可以理解联结表需要使用(Group)联结,并将执行正确的联结
我将为DbContext创建几个扩展功能:
static void GrantPermission(this MyDbContext dbContext, User user, int permissionId)
{
// TODO: check input parameters
var permissionToGrant = dbContext.Permissions
.Where(permission => permission.Id == permissionId)
.FirstOrDefault();
// TODO: decide what to do if not found
user.Permissions.Add(permissionToGrant);
var userToChange = dbContext.Users
}
static void GrantPermission(this MyDbContext dbContext, Permission permission, int userId)
{
// TODO: check input parameters
var userToGrantPermission = dbContext.Users
.Where(user => user.Id == userId)
.FirstToDefault();
// TODO: decide what to do if not found
permission.Users.Add(userToGrantPermission);
}
如果需要,按名称授予权限:
static void GrantPermission(this MyDbContext dbContext, User user, string permissionName)
{
// TODO: check input parameters
var permissionToGrant = dbContext.Permissions
.Where(permission => permission.Name == permissionName)
.FirstOrDefault();
// TODO: decide what to do if not found
user.Permissions.Add(permissionToGrant);
var userToChange = dbContext.Users
}
拒绝权限:
static void GrantPermission(this MyDbContext dbContext, User user, string permissionName)
{
// TODO: check input parameters
var permissionToDeny = dbContext.Permissions
.Where(permission => permission.Name == permissionName)
.FirstOrDefault();
if (permissionToDeny != null)
{
user.Permissions.Remove(permissionToDeny);
}
// else: user does not have this Permission; do nothing
}
// TODO: if desired: add function with userId and permissionName
用法:
using (var dbContext = new MyDbContext()
{
int userId = ...
string permissionName = ...
dbContext.GrantPermission(userId, permissionName);
dbContext.SaveChanges();
}
答案 3 :(得分:1)
我尽了最大的努力来重现问题,但我做不到。
我坚信,您举报行为的原因是SetPermission()
未被认为是您的思维方式。
这是我的代码及其产生的输出。对SetPermission()
方法的唯一更改是使其保持静态,以便使我的代码简短,但不应更改功能。
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace EFTest
{
public class Program
{
static void Main( string[] args )
{
Database.SetInitializer( new DropCreateDatabaseAlways<EFTestContext>() );
User userHans;
User userFranz;
var permissionA = "A";
var permissionB = "B";
using( var context = new EFTestContext() )
{
userHans = context.Users.Add( new User() { Name = "Hans" } ); // Id = 1
userFranz = context.Users.Add( new User() { Name = "Franz" } ); // Id = 2
context.SaveChanges();
}
SetPermission( userHans.Id, true, permissionA );
SetPermission( userHans.Id, true, permissionB );
SetPermission( userFranz.Id, true, permissionA );
SetPermission( userFranz.Id, true, permissionB );
ListAllPermissions();
// 1: A
// 1: B
// 2: A
// 2: B
SetPermission( userFranz.Id, false, permissionA );
ListAllPermissions();
// 1: A
// 1: B
// 2: B
SetPermission( userHans.Id, false, permissionB );
ListAllPermissions();
// 1: A
// 2: B
}
enum PermissionStatus
{
Granted,
Revoked,
}
private static void ListAllPermissions()
{
using( var context = new EFTestContext() )
{
foreach( var permission in context.Permissions )
{
Console.WriteLine( $"{permission.UserId}: {permission.Name}" );
}
}
Console.ReadLine();
}
private static IList<Permission> SetPermission( int userId, bool permissionIsGranted, string key )
{
var permissionStatus = permissionIsGranted ? PermissionStatus.Granted : PermissionStatus.Revoked;
using( var entity = new EFTestContext() )
{
var user = entity.Users.Single( x => x.Id == userId );
var existingPermission = user.Permissions.SingleOrDefault( x => x.Name == key );
switch( permissionStatus )
{
case PermissionStatus.Granted:
if( existingPermission == null )
{
user.Permissions.Add( new Permission { Name = key } );
entity.SaveChanges();
}
break;
case PermissionStatus.Revoked:
if( existingPermission != null )
{
entity.Permissions.Remove( existingPermission );
entity.SaveChanges();
}
break;
}
var permissions = entity.Permissions
.Where( x => x.UserId == userId )
.ToList();
return permissions;
}
}
}
}
出于完整性考虑,我的情况是
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace EFTest
{
public class EFTestContext : DbContext
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Permission> Permissions { get; set; }
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
}
}
public class User
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Permission> Permissions { get; set; }
}
public class Permission
{
[Key, Column( Order = 1 )]
public string Name { get; set; }
[Key, Column( Order = 2 ), ForeignKey( nameof( User ) )]
public int UserId { get; set; }
public virtual User User { get; set; }
}
}