实体框架删除了太多的条目-C#

实体框架删除了太多的条目-C#,c#,sql,entity-framework,entity-framework-6,C#,Sql,Entity Framework,Entity Framework 6,我被实体框架吓坏了。它应该更容易更快,但它只是可怕的 我使用数据库优先的方法处理两个非常简单的表。带有Id和Username的User表,以及带有permissionname和userid的Permission表,这两列上都有主键以及从userid到User.Id的关系 这是我授予和撤销权限的代码: public bool ContributionMarginCustomer { get => GetPermission(_contributionmargin

我被实体框架吓坏了。它应该更容易更快,但它只是可怕的

我使用数据库优先的方法处理两个非常简单的表。带有
Id
Username
User
表,以及带有
permissionname
userid
Permission
表,这两列上都有主键以及从
userid
User.Id
的关系

这是我授予和撤销权限的代码:

   public bool ContributionMarginCustomer
    {
        get => GetPermission(_contributionmarginCustomer);
        set => SetPermission(value, _contributionmarginCustomer);
    }
ContributionMarginCustomer
属性绑定到复选框

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();
    }
}
授予许可非常有效

使用
entity.permission.Remove(existingPermission)
删除数据库中每个用户的权限

我不理解这种行为。你们中有人吗

谢谢

编辑: 用户表

许可证:

使用userId 15和key
CONTRIBUTIONMARGINCUSTOMER将Permissiontable删除后的Permissiontable

编辑2:解决方案

我将permissiontable更改为只有一列作为主键。 这意味着新的permissiontable有三列:Id(自动增量)、Name和UserId,其中Name和UserId具有唯一的键


上面的代码现在可以工作了,但我对此并不满意。

在第二种情况下,您不是从用户中删除权限,而是从实体(基本上是您的整个用户列表)中删除权限。 改为

case PermissionStatus.Revoked:
                if (existingPermission != null)
                {
                    user.Permissions.Remove(existingPermission);
                    entity.SaveChanges();
                }
                break;

在第二种情况下,您不是从用户中删除权限,而是从实体(基本上是您的整个用户列表)中删除权限。 改为

case PermissionStatus.Revoked:
                if (existingPermission != null)
                {
                    user.Permissions.Remove(existingPermission);
                    entity.SaveChanges();
                }
                break;

将权限的状态设置为“已删除”

var existingPermission = user.Permissions.SingleOrDefault(x => x.Name == key);
//your other code here.
entity.Entry(existingPermission).State = EntityState.Removed;
entity.SaveChanges();

将权限的状态设置为“已删除”

var existingPermission = user.Permissions.SingleOrDefault(x => x.Name == key);
//your other code here.
entity.Entry(existingPermission).State = EntityState.Removed;
entity.SaveChanges();

在我看来,您的数据库还不够规范。这会使您的代码更加困难,并在授予/拒绝权限时导致问题

您拥有
用户
权限
。每个
用户
拥有零个或多个
权限
,每个
权限
都已授予零个或多个
用户
。标准的多对多关系

实体内多对多框架的设计如下:

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;}
}
如果需要,按名称授予权限:

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();
}

在我看来,您的数据库还不够规范。这会使您的代码更加困难,并在授予/拒绝权限时导致问题

您拥有
用户
权限
。每个
用户
拥有零个或多个
权限
,每个
权限
都已授予零个或多个
用户
。标准的多对多关系

实体内多对多框架的设计如下:

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;}
}
如果需要,按名称授予权限:

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();
}

我已经尽了最大的努力来重现这个问题,但我就是做不到

我坚信,您报告的行为的原因是
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;
         }
      }
   }
}
使用系统;
使用System.Collections.Generic;
使用System.Data.Entity;
使用System.Linq;
命名空间EFTest
{
公共课程
{
静态void Main(字符串[]参数)
{
SetInitializer(新的DropCreateDatabaseAlways());
用户userHans;
用户userFranz;
var permissionA=“A”;
var permissionB=“B”;
使用(var context=new EFTestContext())
{
userHans=context.Users.Add(new User(){Name=“Hans”});//Id=1
userFranz=context.Users.Add(new User(){Name=“Franz”});//Id=2
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
}
枚举许可状态
{
授予,
撤销的,
}
私有静态void ListAllPermissions()
{
使用(var context=new EFTestContext())
{
foreach(context.Permissions中的var权限)
{
Console.WriteLine($“{permission.UserId}:{permission.Name}”);
}
}
Console.ReadLine();
}
私有静态IList SetPermission(int userId,bool permissionisgrated,string key)
{
var permissionStatus=permissionisgrated?permissionStatus.grated:permissionStatus.reversed;
使用(var entity=new EFTestContext())
{
var user=entity.Users.Single(x=>x.Id==userId);
var existingPermission=user.Permissions.SingleOrDefault(x=>x.Name==key);
交换机(许可状态)
{
案例许可状态。授予:
if(existingPermission==null)
{
user.Permissions.Add(新权限{Name=key});
entity.SaveChanges();
}
打破
案例许可状态。已撤销:
if(existingPermission!=null)
{
实体许可