Linq to custom array object
I am using MVC3/Entity Framework, I need to send a JSON object to be used by a jsTree. The jsTree is calling for the children each time a node is expanded, so each get returns only one set, instead of the whole tree. This is the get function:
public ActionResult GetTreeview(string id, string company)
{
int parentId = Convert.ToInt32(id);
var cats = (from x in db.Categories where x.ICG_PARENT_ID == pa开发者_如何学运维rentId orderby x.ICG_CATEGORY_NAME select new { x.ICG_CATEGORY_ID, x.ICG_PARENT_ID, x.ICG_CATEGORY_NAME }).ToList();
var jsTree = new JsTreeModel[cats.Count];
for (int i = 0; i < cats.Count; i++)
{
jsTree[i] = new JsTreeModel
{
data = cats[i].ICG_CATEGORY_NAME,
attr = new JsTreeAttribute { id = cats[i].ICG_CATEGORY_ID },
state = "closed"
};
}
return Json(jsTree, JsonRequestBehavior.AllowGet);
}
and here is the model:
public class JsTreeModel
{
public string data;
public string state;
public JsTreeAttribute attr;
}
public class JsTreeAttribute
{
public int id;
public bool selected;
}
I am sure a shorter/better way to do this must exist, but I just recently started learning LINQ and lambda expressions (and MVC) and they are not quite intuitive to me yet. Also, I have been using this site as a resource for a long time (it's wonderful) but this is my first question. Is there really no preview button, or am I blind?
EDIT: Updated Model and Function to change the type of attr.Id to int. LINQ to Entities didn't like string conversion.
Simple:
public ActionResult GetTreeview(string id, string company)
{
// company is not being used...
var parentId = Convert.ToInt32(id);
var jsTree =
(from category in db.Categories
where category.ICG_PARENT_ID == parentId
orderby category.ICG_CATEGORY_NAME
select new JsTreeModel
{
data = category.ICG_CATEGORY_NAME,
attr = new JsTreeAttribute { id = category.ICG_CATEGORY_ID.ToString() },
state = "closed",
}).ToArray();
return Json(jsTree, JsonRequestBehavior.AllowGet);
}
For the conditional where clause, there's a couple of ways you could do this and they're not going to make much difference in this isolated example. You could either conditionally use one of two queries that has your where clause:
JsTreeModel[] jsTree;
if (parentId == 0)
{
var companyId = Convert.ToInt32(company);
jsTree = (from category in db.Categories
where category.ICG_PARENT_ID == parentId
&& category.ICG_COMPANY_ID == companyId
//etc...
).ToList();
}
else
{
jsTree = (from category in db.Categories
where category.ICG_PARENT_ID == parentId
//etc..
).ToList();
}
Or you could break the query where you would have inserted the where clause, conditionally append the additional clause, and finish the query:
// get the first part of the query
IQueryable<Category> query = db.Categories
.Where(category => category.ICG_PARENT_ID == parentId);
// conditionally add the where clause
if (parentId == 0)
{
var companyId = Convert.ToInt32(company);
query = query.Where(category => category.ICG_COMPANY_ID == companyId);
}
// finish the query
var jsTree = query
.OrderBy(category => category.ICG_CATEGORY_NAME)
.AsEnumerable() // use LINQ to Objects from this point on
.Select(category => new JsTreeModel
{
data = category.ICG_CATEGORY_NAME,
attr = new JsTreeAttribute { id = category.ICG_CATEGORY_ID.ToString() },
state = "closed",
}).ToArray();
Try:
var jsTree = (from cat in cats
select new JsTreeModel
{
data = cat.ICG_CATEGORY_NAME,
attr = new JsTreeAttribute { id = cat.ICG_CATEGORY_ID.ToString() },
state = "closed"
}).ToArray();
精彩评论