1

I am developing a task tracker web app and you could see the full code here: https://github.com/KimSergey94/TaskTracker

In short, admin, manager, client and employee are users of the app and admin is the boss of these roles. To illustrate, a manager can create a task received by a client and assign it to an employee. The task includes Statuses and Statuses includes Comments. The "roles" have user id as a foreign key to the User table that stores their email addresses and passwords. The Role table stores user id so that they have their roles right.

I need to develop basic functionality, make use some of AJAX, custom filters, stored procedures. There is something wrong with my authorization and roles logic. So, I would appreciate if you take a look and inform me about anything that you feel is not right.

Currently, when I am trying to launch the app and initialise the database, I get the following error:

System.Data.SqlClient.SqlException: 'Introducing FOREIGN KEY constraint 'FK_dbo.Employees_dbo.Users_UserId' on table 'Employees' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

User and Employee classes code:

public class User
    {
        public int UserId { get; set; }
        [DataType(DataType.EmailAddress)]
        [Required]
        public string Email { get; set; }
        public string Password { get; set; }
        public int RoleId { get; set; }

    }
public class Employee
    {
        public int EmployeeId { get; set; }


        //[Required(ErrorMessage = "First Name is required")]
        public string FirstName { get; set; }


        //[Required(ErrorMessage = "Last Name is required")]
        public string LastName { get; set; }

        //[Required(ErrorMessage = "Country field is required")]
        public string Country { get; set; }

        public string Position { get; set; }
        public int Salary { get; set; }

        public int UserId { get; set; }
        [ForeignKey("UserId")]
        public virtual User User { get; set; }

        //public virtual ICollection<Task> Tasks { get; set; }
    }

Globals.asax

protected void Application_Start()
{
    System.Data.Entity.Database.SetInitializer<TaskTrackerContext>(new TaskTrackerDbInitializer());

    var db = new TaskTrackerContext("TaskTrackerContext");
    db.Database.Initialize(true);

    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    ModelValidatorProviders.Providers.Clear();

    NinjectModule orderModule = new OrderModule();
    NinjectModule serviceModule = new ServiceModule("TaskTrackerDb");
    var kernel = new StandardKernel(orderModule, serviceModule);
    DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}

web.config:

<connectionStrings>
    <add name="TaskTrackerContext" 
         connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='|DataDirectory|\TaskTrackerContext.mdf';MultipleActiveResultSets=True; Integrated Security=True" 
         providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <!--
    Initial Catalog=FormsAuth;

</appSettings>

By the way why do I need this Initial Catalog=FormsAuth;?

I noticed that with this parameter I could not instantiate database. I want to get Include functionality for my models

Kim Sergey
  • 29
  • 4
  • Possible duplicate of [Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?](https://stackoverflow.com/questions/17127351/introducing-foreign-key-constraint-may-cause-cycles-or-multiple-cascade-paths) – Jacob Oct 10 '19 at 00:27

2 Answers2

1

In the EF Core, You should disable cascade delete with DeleteBehavior.Restrict or DeleteBehavior.SetNull, e.g. in the database context class, enter a new method

protected override void OnModelCreating(ModelBuilder modelBuilder){ 
   modelBuilder.HasOne(x => x.Employee).WithMany().HasForeignKey(x => 
   x.UserId).OnDelete(DeleteBehavior.Restrict) 
}

If you want cascade behavior, you need to add a nullable integer to the UserId:

public int? UserId { get; set; }

Initial Catalog=FormsAuth; is from the System.Web.Security namespace and is used for form validations, you can read more about it on the Microsoft Docs: https://learn.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication?view=netframework-4.8

I recommend using asp.net identity, I can see a lot of what you are doing is re-inventing the wheel, whereas asp.net does the authentication and validation for you. You can read about it here: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-3.0&tabs=visual-studio

Jacob
  • 371
  • 2
  • 18
0

I had a table that had a circular relationship with others and I was getting the same error. Turns out it is about the foreign key which was not nullable. If the key is not nullable related object must be deleted and circular relations doesn't allow that. So use a nullable foreign key.

public int? UserId { get; }
 [ForeignKey("UserId")]
public virtual User User { get; set; }
  • Thanks! that worked. Now I am thinking to enable migrations if I need that but I always get some errors... Probably I didnt follow a Code-First approach from the beginning. I have 3 projects inside my solution for bl, dl and ui – Kim Sergey Oct 10 '19 at 00:11
  • Is it required to enable migrations in order to get Include and most probably other functionalities? or it is not needed in my case? – Kim Sergey Oct 10 '19 at 00:12
  • It would be easier to do – Jacob Oct 11 '19 at 00:06