views:

205

answers:

2

Hi All,

I am struggling a bit to figure this one out.

I'm working on an ASP.NET MVC project, using LINQ to SQL for my data layer. The database consists of 10 or so different "exceptions" tables, e.g. "Exceptions.LADM", "Exceptions.USB", "Exceptions.GPO". Basically these tables are tracking user+machine information for relaxation of various security procedures.

My LINQ to SQL model has been generated. I have different classes for each table available to me. However, I am not sure how to use them in controller without having to generate separate Controller Actions for each exception type. For List action, I want to do something like this:

// Example Request:  /Exceptions/List/ladm
// Routing:   Controller = "Exceptions", Action = "List", type = "ladm"

// Controller Action:

public ActionResult List(string type)
{
    string viewname = "List-" + type;   // refer to "List-ladm" view.
    if(type == "ladm")
    {
       var items = _repository.ListAllLADMExceptions();
    }

    return View(viewname, items);
}

My repository implements ListAll<XXXXXX>Exceptions methods for each table. Is there a way to avoid 10 different if/else statements? It looks ugly and I'm sure there is a better way that I cannot think of. May be I'm approaching it from incorrect angle.

Any suggestions would be welcomed.

Thanks.

+1  A: 

You could try dynamic method dispatching by using reflection (it's pretty costly, performance-wise):

object items = _repository.GetType().GetMethod("ListAll"+type+"Exceptions")
                          .Invoke(_repository, null);

I would write a switch statement (not if/else) for 10 cases however. It's not that bad.

switch (type) {
    case "ladm": return View("ladm", _repository.ListAllLADMExceptions());
    case "....": return View(....);
}
Mehrdad Afshari
This is one of those cases though, where that performance hit isn't that bad -- you're doing 1 reflection call and a bunch of network IO (handling the request). The network IO is your slow part, not the reflection.Maybe if you were making 100s of reflection calls for each request, you'd care.
Jonathan
Accepting it as final as reflection seems to be a better fit in this scenario. I will benchmark and see how expensive it is compared to if/else or case/switch. Thanks.
nsr81
+2  A: 

The typical pattern is one controller per table. How about repartitioning the variability into multiple controller classes using a common base class? Something like this:

public abstract class ExceptionsBaseController<T> : Controller where T:class 
{
 protected abstract Table<T> ExceptionsTable { get; }

 public virtual ActionResult List()
 {
  var items = ExceptionsTable;
  return View(items);
 }
}

One benefit as I see it would be easier to handle differences between the exception classes and add new ones. It probably won't help your total code line count though, but maybe it can awake ideas.

Cristian Libardo