I want to execute a query like this:
List<supervisorAnswerQuesttionPres> temp =
(from i in dbconnect.tblAnswerLists
where i.StudentNum == studentNumber
select new supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
}).OrderBy(i => i.date).ToList();
My class that this query is returned is something like this :
public class supervisorAnswerQuesttionPres
{
public string date { set; get; }
public List<string> questionList { set; get; }
public List<string> answerList { set; get; }
}
In this query i use a function to convert my Datetime to another presentation i use this function for this :
public string ConvertToPersianToShow(DateTime? datetime)
{
string date;
DateTime dt;
if (!datetime.HasValue) return "";
dt = datetime.Value;
// dt = datetime;
string year = Convert.ToString(persian_date.GetYear(dt));
string month = Convert.ToString(persian_date.GetMonth(dt));
string day = Convert.ToString(persian_date.GetDayOfMonth(dt));
if (month.Length == 1)
{
month = "0" + Convert.ToString(persian_date.GetMonth(dt));
}
if (day.Length == 1)
{
day = "0" + Convert.ToString(persian_date.GetDayOfMonth(dt));
}
Convert.ToString(persian_date.GetMonth(dt)) + "/" +
+ dt.Minute + ")";
date = year + "/" + month + "/" + day;
return date;
}
This function just convert my DateTime ,But when i execute the query i got this error:
Method 'System.String ConvertToPersianToShow(System.Nullable`1[System.DateTime])' has no supported translation to SQL.
It's trying to convert the query into SQL, but doesn't know how to convert the ConvertToPersianToShow method.
The solution is to call ToList() after the where clause to bring the entities into memory, then do the select:
var temp = dbconnect.tblAnswerLists
.Where(i => i.StudentNum == studentNumber)
.ToList() // <-- This will bring the data into memory.
.Select(i => new supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
})
.OrderBy(i => i.date)
.ToList()
When calling ToList(), the query is translated into SQL, e.g. something like
SELECT * FROM <table> WHERE StudentNum = '<studentNumber>'
and executed against the database. When the data returns and you have it in memory, you can use LINQ to Objects to query and manipulate the data further.
NOTE! Generally you should be careful to call ToList before you've added at least a where clause, otherwise you'll end up fetching way too much data into memory.
try this:
var temp = (from i in dbconnect.tblAnswerLists
let pDate = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
where i.StudentNum == studentNumber
select new PresentClass.supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = pDate
}).OrderBy(i => i.date).ToList();
reference: Method x has no supported translation to SQL
LINQ to SQL does not know how to translate a call your method 'ConvertToPersianToShow' into SQL in order to execute the where clause on the server. Your method does not exist on the server.
maybe something like this would help, but if it doesn't work you should fetch your data and then change it to the way you want it to be shown as
List<PresentClass.supervisorAnswerQuesttionPres> temp
= (from i in dbconnect.tblAnswerLists
let PDate=ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
where i.StudentNum == studentNumber
select new PresentClass.supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = PDate
}).OrderBy(i=>i.date).ToList();
As some people have noted, you can't run C# in SQL (well...lets ignore SQL CLR).
However your real problem comes from your poorly architected program.
Your data layer is doing display logic, and none of the Microsoft engineers expected that.
You should bring your data out of the database first. Then on your display logic use ConvertToPersianToShow(DateTime?) to bind to your view.
public class SupervisorAnswerQuestion
{
public DateTime? Date { set; get; }
public List<string> Questions { set; get; }
public List<string> Answers { set; get; }
}
public class SupervisorAnswerQuestionViewModel
{
public SupervisorAnswerQuestion SupervisorAnswerQuestion {get;set;}
public string DateFormated
{
get { return SupervisorAnswerQuestion.Date.ToString("yyyy/MM/dd");
}
}
Actual come to think of it. Scrap ConvertToPersianToShow, learn DateTime.ToString(string) for datetime formatting.
Related
I am working on a C# program. I created an EF code-first database in which I read in a csv file. This csv file contains a DateTime object. This DateTime object was saved in the database. Now I have to get this DateTime and parse it into the DATE (dd-mm-yyyy) and the TIME (hh:mm:ss.fff). Unfortunately I don't know how to solve this problem.
private readonly PerformanceAnalyseToolContext db;
public HomeController(PerformanceAnalyseToolContext db)
{
this.db = db;
}
public IActionResult ReadCsvData(string csvData) //get csvData String
{
ChartData chartData = new ChartData();
string[] lines = csvData.Split("\n"); //Split after enter
//List<ChartData> chartDataList = new List<ChartData>();
foreach (var line in lines)
{
string[] values = line.Split(','); // SPlit after ,
try //try catch, because if an error occurs the process has to continue
{
chartData = new ChartData { //Create object from csv data
Timestamp = Convert.ToDateTime(values[0] + "." + values[1]),
Function = Convert.ToString(values[2]),
Duration = Convert.ToInt32(values[4]),
IsError = Convert.ToBoolean(values[5])
};
db.ChartDatas.Add(chartData); //Save object into database
db.SaveChanges();
}
catch(Exception exc)
{
exc.ToString();
}
}
return View(chartData);
}
public List<ChartDatanDTO> GetDataForChart(string function)
{ //here i get the Data from the DB
return db.ChartDatas
.Where(x => x.Function == function)
.Select(x => new ChartDatanDTO
{
durat = x.Duration,
err = x.IsError,
time =x.Timestamp
})
.ToList();
}
You can specify the format of your DateTime in the ToString method.
time = x.Timestamp.ToString("dd-MM-yyyy hh:mm:ss.fff")
If you need them separated you can do ToString twice.
date = x.Timestamp.ToString("dd-MM-yyyy")
time = x.Timestamp.ToString("hh:mm:ss.fff")
You can use DateTime.ParseExact() method
DateTime dt = DateTime.ParseExact(yourDateTime, "yyyy/MM/DD", CultureInfo.InvariantCulture);
for more info you can check:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/parsing-datetime
Convert function directly doesn't work in LINQ,
So you also can use DBFunctions to truncate time and SqlFunctions.DatePart to get time
........
.Select(x => new ChartDatanDTO
{
date = DbFunctions.TruncateTime(x.YourDateTime),
time = SqlFunctions.DatePart("hh", x.YourDateTime) + ":" +
SqlFunctions.DatePart("mm", x.YourDateTime) +":" +
SqlFunctions.DatePart("ss", x.YourDateTime)
});
Upon completeing the tutorial here:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
I currently use the following
userAccesses = userAccesses.Where(s => s.employeeDetail.employeeNumber.ToUpper().Contains(searchValue.ToUpper()));
However I'd like to concatenate the knownas / surname columns and then do the contains on the concatenated items.
Could anyone explain/suggest an example syntax?
This is what I've attempted below but I'm certain my syntax is incorrect.
userAccesses = userAccesses.Where(s => s.employeeDetail.employeeNumber + " " + s.employeeDetail.knownas + " " + s.employeeDetail.surname).Contains(searchValue);
Thanks for the response everyone, final working version is below.
userAccesses.Where(x => (x.employeeDetail.employeeNumber + x.employeeDetail.knownas + x.employeeDetail.surname).Contains(searchValue));
You should go to this direction
public class Employee
{
public string knownas { get; set; }
public string userName { get; set; }
}
public void Test()
{
List<Employee> employess = new List<Employee>();
string searchvalue = "test";
var listEmplyer = employess.Where(x => (x.userName + x.knownas).Contains(searchvalue));
}
You'll simply need to concatenate the string and call Contains on that string.
userAccesses
.Where(s => $"{s.employeeDetail.employeeNumber} {s.employeeDetail.knownas} {s.employeeDetail.surname}".Contains(searchValue))
If you need an enumerable of strings as the result of the expression, you can also choose to use the following:
userAccesses
.Select(s => $"{s.employeeDetail.employeeNumber} {s.employeeDetail.knownas} {s.employeeDetail.surname}")
.Where(s => s.Contains(searchValue))
Searching through concatenated column values is weird...
I'd suggest smth like this:
var filtered = userAccesses.Where(s => s.employeeDetail.employeeNumber.Contains(searchValue)
|| s.employeeDetail.knownas.Contains(searchValue)
|| s.employeeDetail.surname.Contains(searchValue));
I have the following function that searches a database for entries where a column called "description" have the same value. Right now it just returns the first value it finds or a default value is there isn't one.
public static NewCode GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).FirstOrDefault();
}
I have this if statement to check and make sure the result isn't null, and if it is, to say that the "code isn't found"
[Authorize(parentAction: "Edit")]
public ActionResult Lookup(string Code, int? VersionId = null)
{
var Info = VisitViews.GetDescriptionByVersionId(Code, VersionId.HasValue ? VersionId.Value : 9);
var description = string.Empty;
// CHECK FOR NULL
if (Info != null)
{
description = Info.Description;
if (VersionId == 9)
{
var altInfo = VisitViews.GetAltCode(10, description);
}
if (VersionId == 10)
{
var altInfo = VisitViews.GetAltCode(9, description);
}
}
else
description = "CODE NOT FOUND";
return Json(new { Description = description });
}
My question is, instead of doing FirstOrDefault, is there a way to store the results in an array (or even to store them in a list and call ToArray on the list)? I'm trying to get all of the codes received during the sql search instead of just one so that another function I am working on can traverse the array and place the items where they need to be in a UI.
For future reference of this post, here is the answer:
Change the return type to NewCode[] and replace .FirstOrDefault() with .ToArray()
public static NewCode[] GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).ToArray();
}
I am using MVC platform and a jqGrid in the views. below is the part of controller code return json to the grid
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select Matcher.Calendar(call);
if (jqGridParameters._search != false)
{
callendars = callendars.Where(jqGridParameters.WhereClause);
}
if (jqGridParameters.sidx != null)
callendars = callendars.OrderBy(
jqGridParameters.sidx.Substring(8) + " " + jqGridParameters.sord.ToLower());
var count = callendars.Count();
int pageIndex = jqGridParameters.page;
the Matcher is a static class. below is the used method of the class
public static class Matcher
{
public static CalendarViewModel Calendar(Calendar call)
{
return new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
}
}
at the line
var count = callendars.Count();
i recieve this error:
Method 'KYTC.Models.CalendarViewModel Calendar(KYTC.Data.Calendar)' has no supported translation to SQL.
but when I change the LINQ query to this:
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
my code is running well.
what is wrong with my class definition?
Nothing is wrong with your class definition. The problem is that you simply can't call arbitrary functions in Linq-to-SQL (or EntityFramework) queries. Only a handful of predefined methods can be translated into SQL syntax. Your final method is the correct way of returning CalendarViewModel objects from a query.
However, you could also do this:
public static Expression<Func<Calendar, CalendarViewModel>> CalendarExpression()
{
return c => new CalendarViewModel
{
ID = c.ID,
Name = c.Name,
StartDate = c.StartDate,
EndDate = c.EndDate,
AcademicYear = c.AcademicYear
};
}
var calendarExpr = Match.CalendarExpression();
IQueryable<CalendarViewModel> callendars =
(from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select call)
.Select(calendarExpr);
Below is my code:
string Query = "SELECT EmpName, EmpCode FROM EmpDetail WHERE ZCode=101 ORDER BY EmpName";
var db = new PetaPoco.Database("conCustomer");
var result = db.Fetch<string>(query);
TextBox1.Text = result.ToString(); //This is giving first column
TextBox2.Text = .... // pick second column
I want to know how to pick the second column from the result.
I believe the issue you're having is that you're not using a class as part of the fetch. Try creating a simple class and performing the fetch with that:
public class EmpDetail
{
public string EmpName { get; set; }
public string EmpCode { get; set; }
}
var result = db.Fetch<EmpDetail>(Query);
Then try iterating over that list of EmpDetail:
foreach (var detail in result)
{
var x = detail.EmpName; // First column
var y = detail.EmpCode; // Second column
}
EDIT: According to this (h/t Robert Koritnik), it does look like it will support a dynamic query like so (untested):
foreach (var detail in db.Fetch<dynamic>(query))
{
var x = detail.EmpName; // First column
var y = detail.EmpCode; // Second column
}