In my controller I have a method that looks like this:
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CarCategoryId[0]
select new { search.Manufacturer, search.Model, search.Gear };
I'm trying to get the output of this statement to the view..
ViewData["somename"] = CarModelAndGear;
This way won't work.. I'm getting an error "LINQ to entities does not recognize the method 'Int32 get_Item(Int32)' method, and this method cannot be translated into a store expression. "
How can I get 'CarModelAndGear' to the view?
You need to store the category in a variable first because the provider is not able to interpret the list indexer method:
int CatId = CarCategoryId[0];
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CatId
select new { search.Manufacturer, search.Model, search.Gear };
You are using LinqToSql here. So what it is trying to do is convert that Linq expression into a SQL statement.
While you can access an item in a collection from C#, this cannot be translated into SQL, so it falls over.
Try this rather:
var id = CarCategoryId[0];
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == id
select new { search.Manufacturer, search.Model, search.Gear };
You can execute linq and then assign to ViewData
ViewData["somename"] = CarModelAndGear.ToList();
But i prefer approach described by live2, when you will combine everything to model and then pass the model
Create a model for your result
public class CarViewResult
{
public string Manufacturer { get; set; }
public string Model { get; set; }
public string Gear { get; set; }
public CarViewResult(string manufacturer, string model, string gear)
{
this.Manufacturer = manufacturer;
this.Model = model;
this.Gear = gear;
}
}
Add add the new model to your LINQ query
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CarCategoryId[0]
select new CarViewResult(search.Manufacturer, search.Model, search.Gear);
ViewData["somename"] = CarModelAndGear.ToList();
Related
I want to get an property value from an object that is in a list and put it into textbox.text
Below i have an example of my code:
The object:
public class Incident
{
public int Incident_id { get; set; }
public string Description { get; set; }
public string Caller { get; set; }
}
Below is my code in my form class:
List<Incident> incidentById = new List<Incident>();
incidentById = db.GetIncidentById(ID);
when my list is filled i want to put the string Caller into an textbox somewhat like below:
textBoxCaller.Text = incidentById[1].Caller;
I'm stuck at this point so i hope someone can help me out.
Thanks!
EDIT:
public List<Incident> GetIncidentById(int id)
{
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(Helper.CnnVal("IncidentLog")))
{
var output = connection.Query<Incident> ($"select * from Incidents where Incident_id like #id", new { id = "%id%" }).ToList();
return output;
}
}
I wasn't passing the right value into my query
this did the trick!
What you want is $"select * from Incidents where Incident_id = #id", new { id }
do you want first value should go?
check like.
if(incidentById.Count>0)
{
textBoxCaller.Text = incidentById.First().Caller;
}
// or you can join all Caller in list like
if(incidentById.Count>0)
{
textBoxCaller.Text = string.join(",",incidentById.Select(x=>x.Caller));
}
The issue that you are facing is that you are trying to access the second element in the list when there are not two or more elements in the list. If you are trying to access the first element in the list, then you could do either
textBoxCaller.Text = incidentById[0].Caller;
or
textBoxCaller.Text = incidentById.First().Caller;
If you do in fact want the second element of the list, then you should be checking to verify that it's length is at least two:
if(incidentById.Count >= 2)
{
...
}
Finally, as mentioned in a comment, you should rename GetIncidentById to something that makes clear it is returning a list, like GetIncidentsById or something similar.
I've been reading articles and SO posts for the last couple of hours about building my own Linq Expressions dynamically, then using those as predicates to filter items in a List or and Array.
Here's a simple example of what I have so far:
public class AWDRiskMRASCodeXref
{
public string RiskSubType { get; set; }
public string AcordReqCodeInt { get; set; }
public string MrasReqCodeInt { get; set; }
public string AcordReqCodePpe { get; set; }
public string MrasReqCodePpe { get; set; }
public string AcordReqCodeWeb { get; set; }
public string MrasReqCodeWebS { get; set; }
}
I will then use something like Dapper to retrieve the list from the database;
var items = conn.Query<AWDRiskMRASCodeXref>("SELECT RiskSubType, AcordReqCodeInt, MrasReqCodeInt, AcordReqCodePpe, MrasReqCodePpe, AcordReqCodeWeb, MrasReqCodeWeb FROM LKUP_AWDRiskMRASCodeXref;").ToList();
var param = Expression.Parameter(typeof(AWDRiskMRASCodeXref), "x");
var member = Expression.Property(param, "AcordReqCodePpe"); //x.AcordReqCodePpe
var constant = Expression.Constant("1004700009");
var body = Expression.Equal(member, constant); //x.AcordReqCodePpe == "1004700009"
var finalExpression = Expression.Lambda<Func<AWDRiskMRASCodeXref, bool>>(body, param); //x => x.AcordReqCodePpe == "1004700009"
finalExpression.Dump();
The finalExpression "x => (x.AcordReqCodePpe == "1004700009")" looks great in LinqPad, but what do I need to do the the express to enable it to be passed the the following Linq query?
var item = items.FirstOrDefault(finalExpression);
Thank you,
Stephen
Since you've already pulled the data from your database, all you need to do for your expression to work is to compile it and pass it to FirstOrDefault extension method instead.
var compiledExpression = finalExpression.Compile();
var item = items.FirstOrDefault(compiledExpression);
As a bonus tip, if you're using .NET Framework 4.6 or higher. You could use the nameof operator while generating your member property. It's much better than the hardcoded string, if you ever change the name of your property. It'd look like this:
var member = Expression.Property(param, nameof(AWDRiskMRASCodeXref.AcordReqCodePpe));
The problem is that you have already 'resolved' the query when you called .ToList() on the query. Remove that so that your query reads something like:
var item = conn.Query<AWDRiskMRASCodeXref>("SELECT RiskSubType, AcordReqCodeInt, MrasReqCodeInt, AcordReqCodePpe, MrasReqCodePpe, AcordReqCodeWeb, MrasReqCodeWeb FROM LKUP_AWDRiskMRASCodeXref;")
.FirstOrDefault(finalExpression);
My controller file contains as below.
public ActionResult Index()
{
CityNameList ct = dt.AllCity(); /*Returns Citynames. Used Linq to Sql Classes to retrieve from DB. */
return View(ct);
}
And in CityNameList.cs file in Model
public class CityNameList
{
public IEnumerable<string> CityName {get;set;}
}
Really tried lot fix the issue, but no use.
I am new to MVC. I need clear idea to pass the data to View from result of Stored Procedure in Controller.
Looks like you're using LinqToSql. If the stored procedure returning the ISingleResult then you need to enumerate the result to get the data. You can invoke ToList() to convert the result to IEnumerable. Also it looks like
var result = dt.AllCity();
CityNameList ct = null;
if (result != null && result.Any()) {
ct = new CityNameList { CityName = result.ToList()};
}
return View(ct);
Change CityNameList class properties to below:
public class CityNameList
{
public string CityName{ get; set; }
}
And add Another class to map stored procedure output to Class CityNameList like below.
public class CityDataContext
{
DataDataContext dt = new DataDataContext();
public IEnumerable<CityNameList> DisplayName
{
get
{
List<CityNameList> Details = new List<CityNameList>();
var result = dt.AllCity().ToList();
for (int j = 0; j < result.Count;j++ )
{
CityNameList city = new CityNameList();
city .CityName= Convert.ToString(result[j].cityname);
Details.Add(city);
}
return Details;
}
}
}
Where cityname within for loop is column name of table which will be returning after executing stored procedure in DB, And finally add Strongly typed view with Model Class CityNameList.It will be working fine....
I am using generic method to fill my dropdown for all types
below is my code.
the entity type are as follow
public class Role
{
public string Id { get; set; }
public string Name { get; set; }
}
public class DropDown
{
public string Id { get; set; }
public string Name { get; set; }
}
i am able to fetch data successfully at
var data = DataFetcher.FetchData<T>();
private static void Main( string[] args )
{
List<DropDown> cities = BLL.GetDataList<City>();
List<DropDown> states = BLL.GetDataList<State>();
List<DropDown> roles = BLL.GetDataList<Role>();
}
public static class BLL
{
public static List<DropDown> GetDataList<T>() where T : class ,new()
{
var data = DataFetcher.FetchData<T>();
return data as List<DropDown>;
}
}
I knew this cast data as List<DropDown> will fail,thats why its returning null back to calling method,
How can i cast Generic list to List of Known Type?
You have to ask yourself: how do I want to convert T to DropDown? If you can't answer this, the answer is: you can't.
I guess your DropDown class has an object Value property, that holds the dropdown value, and you wish to assign the data entity to that property.
Then you can project the list of data entities to DropDowns as such:
var data = DataFetcher.FetchData<T>();
return data.Select(d => new DropDown { Value = d }).ToList();
As for your edit: so you have at least one type, the displayed Role, that has an Id and Name property. But type T doesn't guarantee this, so you'd need to introduce an interface:
public interface INamedIdentifyableEntity
{
string Id { get; set; }
string Name { get; set; }
}
And apply this to your entities. Then introduce it as a generic constraint and do the mapping:
return data.Select(d => new DropDown
{
Id = d.Id,
Name = d.Name,
}).ToList();
But you don't want this, as here you are tying these two properties to dropdowns. Tomorrow you'll want an entity with Code instead of Id and Text instead of Name, so you'll have to add more interfaces, more overloads, and so on.
Instead you might want to use reflection, where you can specify the member names in the call:
List<DropDown> cities = BLL.GetDataList<City>(valueMember: c => c.CityCode, displayMember: c => c.FullCityname);
And use these member expressions to look up data's values and fill those into the DropDown.
However, you're then reinventing the wheel. Leave out your DropDown class entirely, and leave the dropdown generation to the front end, in this case MVC:
var cities = DataFetcher.FetchData<City>();
var selectList = new SelectList(cities.Select(c => new SelectListItem
{
Selected = (c.Id == selectedCityId),
Text = c.FullCityName,
Value = c.CityCode,
});
Or:
var selectList = new SelectList(cities, "CityCode" , "FullCityName", selectedCityId);
One solution is to use AutoMapper.
First create a map between your models like this:
AutoMapper.Mapper.CreateMap<Role, DropDown>();
Do the same thing for City and State classes if you need to.
Then you can use AutpMapper to convert your objects to DropDown like this:
public static List<DropDown> GetDataList<T>() where T : class ,new()
{
var data = DataFetcher.FetchData<T>();
return data.Select(x => AutoMapper.Mapper.Map<DropDown>(x)).ToList();
}
If I understood the question correctly, you could use Linq as follows.
return data.Cast<DropDown>().ToList();
On .ascx.cs I have this code, for example :
var xDoc = XDocument.Parse(xml); //or XDocument.Load(fileName)
var list = xDoc.Descendants("ordinanza")
.Select(n => new
{
Numero = n.Element("numero").Value,
Titolo = n.Element("titolo").Value,
})
.ToList();
Well, now I'd like to "foreach" this anonymous type on my .ascx, but I can't use protected/public for list (because is var).
So, how can I do it?
The data you're extracting is a cut-down version of a larger entity, and you're using this data in a view. This in MVC or MVP terms would be a view model (a type of data transfer object for displaying data in the UI).
What you could do is create a simple lightweight class (view model) to hold this data:
public CustomerContactViewModel()
{
public string Name { get; set; }
public string Phone { get; set; }
}
and then update your LINQ query to:
IEnumerable<CustomerContactViewModel> custQuery =
from cust in customers
where cust.City == "Phoenix"
select new CustomerContactViewModel() { Name = cust.Name, Phone = cust.Phone };