0

Я использую asp.net mvc 4 и структуру сущности 5 в проекте. У меня есть базовый Entity, что все объекты, производный от него:StackOverflowException был необработанным: необработанное исключение типа «System.StackOverflowException» произошло в mscorlib.dll

public abstract class BaseEntity 
{   
    [Required] 
    public virtual int Id { get; set; } 

    [Required] 
    public virtual DateTime CreatedOn { set; get; } 

    public virtual string CreatedBy { set; get; } 

    [Required] 
    public virtual DateTime ModifiedOn { set; get; } 

    public virtual string ModifiedBy { set; get; } 
} 

Сначала Entity учетная запись является классом для пользователя приложения:

public class Account : BaseEntity 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 
    public byte[] AvatarBinary { get; set; } 
    public string AvatarMimeType { get; set; } 

    public virtual IList<AccountInRole> AccountRoles { get; set; } 
} 

Роль пользователя:

public class Role : BaseEntity 
{ 
    public string RoleName { get; set; } 

    public virtual IList<AccountInRole> AccountRoles { get; set; } 
} 

каждый Пользователь может иметь несколько ролей и наоборот:

public class AccountInRole : BaseEntity 
{ 
    public int AccountId { get; set; } 
    public int RoleId { get; set; } 

    public virtual Account Account { get; set; } 
    public virtual Role Role { get; set; } 
} 

Когда я хочу дать роли для конкретного пользователя, вызовите метод GetRoles в Accountrepository. это реализуется следующим образом:

public class AccountRepository : IAccountRepository 
{ 
#region Properties 
private CharityContext DataContext { get; set; } 

public IQueryable<Account> Accounts 
{ 
    get { return DataContext.Accounts; } 
} 

#endregion 

#region Ctors 

public AccountRepository() : this(new CharityContext()) 
{ 
} 

public AccountRepository(CharityContext db) 
{ 
    DataContext = db; 
} 

#endregion 

#region Methods 

public List<Role> GetRoles(string userName) 
{ 
    var acc = DataContext.Accounts; 

    var query = from u in DataContext.Accounts 
       from r in DataContext.Roles 
       from ur in DataContext.AccountInRoles 
       where ur.AccountId == u.Id && ur.RoleId == r.Id && u.UserName == userName 
       select r; 
    return query.ToList(); 
} 

#endregion 

} 

в этом методе исключение генерируется, когда компилятор хочет запустить выше LINQ запрос. это исключение:

StackOverflowException был необработанным

Необработанного исключение типа «System.StackOverflowException» произошло в mscorlib.dll

{Не могу оценить выражение, так как текущий поток в состояние переполнения стека.}

Метод GetRoles вызывает два раза:

один раз из атрибутов Пользовательские Authorize:

public class CustomAuthorize : AuthorizeAttribute 
{ 
    //private readonly IAccountRepository _accountRepository; 
    private string[] roles; 

    //public CustomAuthorize(params string[] roles) 
    //{ 
    // this.roles = roles; 
    //} 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (httpContext == null) 
      throw new ArgumentNullException("httpContext"); 

     if (!httpContext.User.Identity.IsAuthenticated) 
      return false; 

     if (Roles == string.Empty) 
      return true; 

     var lstRoles = Roles.Split(','); 
     AccountRepository _accountRepository = new AccountRepository(); 
     var userRoles = _accountRepository.GetRoles(httpContext.User.Identity.Name); 
     foreach (var role in lstRoles) 
     { 
      bool isFound = false; 
      foreach (var userRole in userRoles) 
      { 
       if (userRole.RoleName == role) 
        isFound = true; 
      } 
      if (!isFound) return false; 
     } 

     return true; 
    }   
} 

и второй раз от метода Application_AuthenticateRequest в Global.asax.cs:

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
{ 
    string cookie = FormsAuthentication.FormsCookieName; 
    HttpCookie httpCookie = Request.Cookies[cookie]; 
    if (httpCookie == null) return; 
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(httpCookie.Value); 
    if(ticket == null || ticket.Expired) return; 
    FormsIdentity identity = new FormsIdentity(ticket); 
    var _accountRepository = new AccountRepository(); 
    var roles = _accountRepository.GetRoles(identity.Name); 
    var principal = new CharityAccount(identity.Name, roles.Select(x => x.RoleName).ToArray()); 
    Context.User = Thread.CurrentPrincipal = principal; 
} 

CharityAccount, что НУ может увидеть его в выше метода является осуществляются таким образом:

public class CharityAccount : IPrincipal 
{ 
    private string[] roles; 
    private IIdentity identity; 

    public IIdentity Identity 
    { 
     get { return identity; } 
    } 

    public bool IsInRole(string role) 
    { 
     return Array.IndexOf(roles, role) >= 0; 
    } 

    public CharityAccount(String name, String[] roles) 
    { 
     identity = new GenericIdentity(name, "Custom authentication"); 
     this.roles = roles; 
    } 
} 

Согласно вашей идее, в чем проблема? Отношения

+0

Почему отрицательный класс? я не понимаю –

+0

Я бы предположил, что нижний предел для большого объема информации - вы не сузили это до места возникновения проблемы.Вероятно, ваш stackoverlow происходит из-за чрезмерной рекурсии - я бы предложил проверить внешние ключи вашего объекта, чтобы убедиться, что вы не настроили круговую ссылку. – Paddy

+0

Я проверяю круглые ссылки, нет никаких круговых ссылок. эти коды работают нормально, но когда я добавляю вторую ** отдельную ** базу данных, используя сначала код ef для ведения журнала, эта ошибка произошла. –

ответ

1

Вы сделали несколько вещей, которые могут привести вас к неприятностям. Единственное, что я вижу, это круговая ссылка учетных записей, роли в AccountinRoles и наоборот.

Я упростил ваш код, хотя это не лучший дизайн (но я считаю, что все в порядке вещей и глупо). Вы можете сохранить свои виртуальные свойства, если вы действительно имеете в виду, что для виртуальных объектов для объектов.

Это работает и работает отлично.

public abstract class BaseEntity 
{ 
    public int Id { get; set; } 
    public DateTime CreatedOn { set; get; } 
} 

public class Account : BaseEntity 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 
} 

public class Role : BaseEntity 
{ 
    public string RoleName { get; set; } 
} 

public class AccountInRole 
{ 
    public int AccountId { get; set; } 
    public int RoleId { get; set; } 
} 

public class Operation 
{ 
    public List<Role> GetRoles() 
    { 
     List<Account> lstAccount = new List<Account>(); 
     List<Role> lstRole = new List<Role>(); 
     List<AccountInRole> lstAccountInRoles = new List<AccountInRole>(); 

     Account ac1 = new Account 
      { 
       Id = 1, 
       UserName = "Jack", 
       Password = "somePassword2", 
       CreatedOn = DateTime.Now 
      }; 
     Account ac2 = new Account 
     { 
      Id = 2, 
      UserName = "Sam", 
      Password = "somePassword1", 
      CreatedOn = DateTime.Now 
     }; 
     lstAccount.Add(ac1); 
     lstAccount.Add(ac2); 

     Role r1 = new Role 
      { 
       Id = 1, 
       RoleName = "TestRole1", 
       CreatedOn = DateTime.Now 
      }; 
     Role r2 = new Role 
     { 
      Id = 2, 
      RoleName = "TestRole2", 
      CreatedOn = DateTime.Now 
     }; 
     lstRole.Add(r1); 
     lstRole.Add(r2); 

     AccountInRole acRole1 = new AccountInRole 
      { 
       AccountId = ac1.Id, 
       RoleId = r1.Id 
      }; 

     AccountInRole acRole2 = new AccountInRole 
     { 
      AccountId = ac2.Id, 
      RoleId = r2.Id 
     }; 
     lstAccountInRoles.Add(acRole1); 
     lstAccountInRoles.Add(acRole2); 

     string userName = "Sam"; 

     // Query the data 
     var roles = from u in lstAccount 
        where u.UserName == userName 
        from acc in lstAccountInRoles 
        from r in lstRole 
        where acc.AccountId == u.Id 
        && r.Id == acc.RoleId 
        select r; 

     return roles.ToList(); 
    } 
} 
+0

Спасибо, но отношения между объектами Account и Role много для многих. Он не должен меняться. Я восстанавливаю проект из резервной копии и теперь отлично работает. Но я точно не знаю, что вызвало эту ошибку. –