1

I'm really new to ASP.NET MVC & Entity Framework and it's giving me so many headaches. I've gone through all of the similar questions and I've come up empty. I cannot find any good resources on ASP.NET MVC Error Handling!

Here are my models:

namespace ServerManager.Models
{
    public class Domain
    {
        public Domain()
        {
            this.Id = Guid.NewGuid();
            this.Servers = new HashSet<Server>();
        }

        [Key]
        [Required]
        public Guid Id { get; set; }

        [Required]
        [Display(Name="Domain Name")]
        public string Name { get; set; }

        [Required]
        [Display(Name="Fully-Qualified Name")]
        public string FullyQualifiedName { get; set; }

        [Display(Name="Servers")]
        public virtual ICollection<Server> Servers { get; set; }
    }

    public class Server
    {
        public Server()
        {
            this.Id = Guid.NewGuid();
        }

        [Required]
        [StringLength(25)]
        [Display(Name="Server Name")]
        public string Name { get; set; }

        public virtual Domain Domain { get; set; }

        [Required]
        [Display(Name = "Domain")]
        public virtual Guid DomainId { get; set; }
    }
}

I'm looking to be able to access the Server.Domain property to lazily access the Domain for the Server object I'm working with (which works) and conversely, I'm looking to access the Domain.Servers property (which kind of works). The problem is that when I delete a Domain object using the DbContext, a cascading delete takes place. The desired effect that I'm going for is to not allow the user to delete a Domain object while there are still Server objects using the Domain. How can I achieve this without displaying a generic Error message?

Martin T.
  • 445
  • 1
  • 7
  • 18
  • In your context class you can override the method OnModelCreating and set the cascade options. Some articles [here](http://geekswithblogs.net/danemorgridge/archive/2010/12/17/ef4-cpt5-code-first-remove-cascading-deletes.aspx), [here](http://www.codeproject.com/Articles/165720/Using-the-Code-First-Model-Configuration-Classes) and [here](http://stackoverflow.com/questions/13705441/how-to-disable-cascade-delete-for-link-tables-in-ef-code-first) – pln Oct 01 '14 at 13:38
  • Yeah, buddy. As indicated in the question, I've looked at all of those links before and Fluent caused more problems for me in the end. It's probably that I don't fully understand how to map relationships using Fluent as of yet, so maybe I can look into it a bit more. – Martin T. Oct 01 '14 at 14:55
  • Dont see those or fluent referenced in your question. This is the way to go if you really want the correct cascade rules. – pln Oct 01 '14 at 15:03

1 Answers1

1

Let's say you write a query like this to find the Domain object:

Guid id = Guid.Parse("...");
Domain domain = db.Domains.Find(id);

You can write another query to determine if it has any Servers:

bool hasServers = db.Servers.Any(s => s.DomainId == domain.Id);

You could also combine it into a single query:

var domainAndServers = db.Domains.Include("Servers").SingleOrDefault(d => d.Id == id);

Or something like this:

var domainAndServerCount = from d in db.Domains
                           where d.Id == id
                           select new
                           {
                               Domain = d,
                               ServerCount = d.Servers.Count()
                           };

You can use those properties to populate your view model whether you can allow deletion or not:

DomainViewModel vm = new DomainViewModel();
vm.CanBeDeleted = hasServers;
// or
vm.CanBeDeleted = domain.Servers.Count() > 0;

The domain.Servers.Count() > 0 will work if you have lazy loading, so you wouldn't necessarily need to write your query using Include.

Dismissile
  • 32,564
  • 38
  • 174
  • 263
  • To be honest, you're totally right! I was over-complicating it in my head. Just as a side note, I also updated the POST action for Delete so that it throws a `NotSupportedException` if the `domain.Servers.Count()` is greater than 0. That way you can't submit a POST request to delete the Domain, which will cause a cascade delete to occur. – Martin T. Oct 01 '14 at 14:53