By splitting this method into multiple smaller methods you can reduce the complexity of this method.
if (query == "" && accountId == null)
{
return Json(empty, JsonRequestBehavior.AllowGet);
}
if (query == "" && accountId != null)
{
var search = Db.Entities.Find(accountId);
var suggestions = Db.Entities.Where(
x => x.Name.Contains(search.Name) && x.EntityId != accountId && !String.IsNullOrEmpty(x.Group.Label))
.ToList()
.Select(item => new { id = item.GroupId, text = item.Group.Label });
return Json(suggestions, JsonRequestBehavior.AllowGet);
}
here you have one common condition which is query == ""
so let us extract this to a separate method.
private ActionResult *********1(int? accountId = null)
{
if (accountId == null)
{
return Json(new object(), JsonRequestBehavior.AllowGet);
}
var search = Db.Entities.Find(accountId);
var suggestions = Db.Entities.Where(
x => x.Name.Contains(search.Name) && x.EntityId != accountId && !String.IsNullOrEmpty(x.Group.Label))
.ToList()
.Select(item => new { id = item.GroupId, text = item.Group.Label });
return Json(suggestions, JsonRequestBehavior.AllowGet);
}
leaving the original like
public ActionResult *********(string query = "", int? id = null, int? accountId = null)
{
if (query == "")
{
return *********1(accountId);
}
if (id != null)
{
var accountGroup = Db.Groups.Find(id);
if (accountGroup != null)
return Json(new { id = accountGroup.GroupId, text = accountGroup.Label },
JsonRequestBehavior.AllowGet);
return Json(null, JsonRequestBehavior.AllowGet);
}
var list = Db.Groups.Where(
r => !String.IsNullOrEmpty(query) && query.Length > 2 && (r.StatusId == GroupStatus.Both || r.StatusId == GroupStatus.Customer) && r.Label.ToLower().Contains(query.ToLower())).OrderBy(r => r.Label).Select(item => new { id = item.GroupId, text = item.Label }).ToList();
if (!list.Any())
{
return Json(new List<object>() { new { id = query, text = query } }, JsonRequestBehavior.AllowGet);
}
return Json(list, JsonRequestBehavior.AllowGet);
}
Next I would extract the part where (id != null)
.
private ActionResult *********2(int? id = null)
{
var accountGroup = Db.Groups.Find(id);
if (accountGroup != null)
{
return Json(new { id = accountGroup.GroupId, text = accountGroup.Label },
JsonRequestBehavior.AllowGet);
}
return Json(null, JsonRequestBehavior.AllowGet);
}
which results in the original looking like
public ActionResult *********(string query = "", int? id = null, int? accountId = null)
{
if (query == "")
{
return *********1(accountId);
}
if (id != null)
{
return *********2(id);
}
var list = Db.Groups.Where(
r => !String.IsNullOrEmpty(query) && query.Length > 2 && (r.StatusId == GroupStatus.Both || r.StatusId == GroupStatus.Customer) && r.Label.ToLower().Contains(query.ToLower())).OrderBy(r => r.Label).Select(item => new { id = item.GroupId, text = item.Label }).ToList();
if (!list.Any())
{
return Json(new List<object>() { new { id = query, text = query } }, JsonRequestBehavior.AllowGet);
}
return Json(list, JsonRequestBehavior.AllowGet);
}
Next I would refactor this monster linq query like
public ActionResult *********(string query = "", int? id = null, int? accountId = null)
{
if (query == "")
{
return *********1(accountId);
}
if (id != null)
{
return *********2(id);
}
if (query != null && query.Length > 2)
{
string lowerQuery = query.ToLower();
var list = Db.Groups.Where(r => (r.StatusId == GroupStatus.Both || r.StatusId == GroupStatus.Customer) && r.Label.ToLower().Contains(lowerQuery))
.OrderBy(r => r.Label)
.Select(item => new { id = item.GroupId, text = item.Label });
// removed the call of ToList() because you only need to test if at least one item is in the list.
// This results in 1 additional trip to the database if at least one item is found.
if (list.Any())
{
return Json(list.ToList(), JsonRequestBehavior.AllowGet);
}
}
return Json(new List<object>() { new { id = query, text = query } }, JsonRequestBehavior.AllowGet);
}
By changing the order of conditions you can speed up the queries too.
var suggestions = Db.Entities.Where(
x => x.Name.Contains(search.Name) && x.EntityId != accountId && !String.IsNullOrEmpty(x.Group.Label))....
the fastest check would be x.EntityId != accountId
followed by !String.IsNullOrEmpty(x.Group.Label)
and last x.Name.Contains(search.Name)
.
You should be consistent with the coding style you use. Some times you are using braces {}
for single instrauction if
or else
and sometimes not. Although there is no explicit rule about using them, I would like to encourage you to always use them to make your code less error prone.
I have no idea about your domain model, but I would like to suggest to rename some of your variables to a better more meaningful name.
var search = Db.Entities.Find(accountId); // looks more like a searchResult
var list = Db.Groups.Where() // list is not the best name either
*****();
or*****(someStringVariable);
– Heslacher May 13 at 10:19