SQL Select on MVC4 Controller - sql

I am trying to perform a SELECT on the M1lhao table of Sorteio entity (database).
I don't want to go the traditional "string query" or AddWithParameter() way, i wanted to use the MVC4 EF5 available methods.
The following code passes the entire Table to the View, that i can do a foreach in the View and all works fine. What i am looking for is how can i do a SQL query, so i can pass only the element(s) i want, sorted DESCending (for example), obviously on a List and obeying the Model that the View expects.
Essentially i want a replacement for (i tried variants too, db.Milhao, etc):
var data = db.Database.ExecuteSqlCommand("SELECT * From M1lhao WHERE DrawID = {0}", id);
The problem with Find() is that it only searches primary keys.
The complete code:
public class M1lhaoController : Controller
{
private Sorteio db = new Sorteio();
public ActionResult Index(int id = 1)
{
var data = db.Database.ExecuteSqlCommand("SELECT * From M1lhao WHERE DrawID = {0}", id); // the variable data comes as -1
M1lhao m1lhao = db.M1lhao.Find(id);
if (m1lhao == null)
{
return HttpNotFound();
}
return View(db.M1lhao.ToList());
}
}
Thank you.

You can try as shown below.
var data = db.M1lhao.Where(m=>m.DrawID == id).Select(p=>p);
You can learn more about Method-Based Query Syntax : Projection

Related

Update context in SQL Server from ASP.NET Core 2.2

_context.Update(v) ;
_context.SaveChanges();
When I use this code then SQL Server adds a new record instead of updating the
current context
[HttpPost]
public IActionResult PageVote(List<string> Sar)
{
string name_voter = ViewBag.getValue = TempData["Namevalue"];
int count = 0;
foreach (var item in Sar)
{
count = count + 1;
}
if (count == 6)
{
Vote v = new Vote()
{
VoteSarparast1 = Sar[0],
VoteSarparast2 = Sar[1],
VoteSarparast3 = Sar[2],
VoteSarparast4 = Sar[3],
VoteSarparast5 = Sar[4],
VoteSarparast6 = Sar[5],
};
var voter = _context.Votes.FirstOrDefault(u => u.Voter == name_voter && u.IsVoted == true);
if (voter == null)
{
v.IsVoted = true;
v.Voter = name_voter;
_context.Add(v);
_context.SaveChanges();
ViewBag.Greeting = "رای شما با موفقیت ثبت شد";
return RedirectToAction(nameof(end));
}
v.IsVoted = true;
v.Voter = name_voter;
_context.Update(v);
_context.SaveChanges();
return RedirectToAction(nameof(end));
}
else
{
return View(_context.Applicants.ToList());
}
}
You need to tell the DbContext about your entity. If you do var vote = new Vote() vote has no Id. The DbContext see this and thinks you want to Add a new entity, so it simply does that. The DbContext tracks all the entities that you load from it, but since this is just a new instance, it has no idea about it.
To actually perform an update, you have two options:
1 - Load the Vote from the database in some way; If you get an Id, use that to find it.
// Loads the current vote by its id (or whatever other field..)
var existingVote = context.Votes.Single(p => p.Id == id_from_param);
// Perform the changes you want..
existingVote.SomeField = "NewValue";
// Then call save normally.
context.SaveChanges();
2 - Or if you don't want to load it from Db, you have to manually tell the DbContext what to do:
// create a new "vote"...
var vote = new Vote
{
// Since it's an update, you must have the Id somehow.. so you must set it manually
Id = id_from_param,
// do the changes you want. Be careful, because this can cause data loss!
SomeField = "NewValue"
};
// This is you telling the DbContext: Hey, I control this entity.
// I know it exists in the DB and it's modified
context.Entry(vote).State = EntityState.Modified;
// Then call save normally.
context.SaveChanges();
Either of those two approaches should fix your issue, but I suggest you read a little bit more about how Entity Framework works. This is crucial for the success (and performance) of your apps. Especially option 2 above can cause many many issues. There's a reason why the DbContext keep track of entities, so you don't have to. It's very complicated and things can go south fast.
Some links for you:
ChangeTracker in Entity Framework Core
Working with Disconnected Entity Graph in Entity Framework Core

How Do I Return the Index of type T in a Collection based on some criteria?

Kotlin has some pretty cool functions for collections. However, I have come across a problem in which the solution is not apparent to me.
I have a List of Objects. Those Objects have an ID field which coincides with a SQLite database. SQL operations are performed on the database, and a new list is generated. How can the index of an item from the new list be found based on the "ID" field (or any other field for that matter)?
the Collection.find{} function return the object, but not the index.
indexOfFirst can find the index of the first element of a collection that satisfies a specified predicate.
We have a DB SQlite that a call is made to to retrieve parentList We can obtain the items in the ArrayList with this type of code
fun onDoIt(view: View){
initDB()
for (t in 0..X-1) {
var N:String = parentList[t].dept
// NOTE two syntax here [t] and get(t)
if(t == 1){
var B:String = parentList[0].idD.toString()
println("$$$$$$$$$$$$$$$$$$$$$ ====== "+B)
}
var I:String = parentList.get(t).idD.toString()
println("################### id "+I+" for "+N)
}
}
private fun initDB() {
parentList = db.querySPDept()
if (parentList.isEmpty()) {
title = "No Records in DB"
} else {
X = parentList.size
println("**************************************** SIZE " + X)
title = "SP View Activity"
}
}

Entity Framework 4.1 Eager Loading on complext object

In a current MVC4.0 project I am using Entity Framework 4.1 Database first model.
Part of this structure includes the following tables
compGroupData
SurveyData
SecondaryData
compGroupData and SurveyData are not joined in the database
SecondaryData is joined to SurveyData on a one to one relationship via a Foreign Key SurveyData.surveydatakey = SecondaryData.surveydatakey
In my project I have a class ComparisonWithData defined as:
public class ComparisonWithData
{
public compGroupData compgrp { get; set; }
public SurveyData surveydata { get; set; }
public ComparisonWithData()
{
compgrp = new compGroupData();
surveydata = new SurveyData();
}
}
This gives me a result set for a specific Comparison group and the data that matches this.
In the past I have retrieved the data for this via the following query:
List<ComparisonWithData> comparisonwithdata = ((from compgrp in db.compGroupDatas
where compgrp.grpYear == rptyear && compgrp.CompGroupID == ccompgrp.CompGrpID
join surveydata in db.SurveyDatas on new { compgrp.companyid, SurveyYear = (Int32)compgrp.SurveyYear } equals new { companyid = surveydata.companyid, SurveyYear = surveydata.surveyyear }
select new ComparisonWithData
{
compgrp = compgrp,
surveydata = surveydata,
}
)).ToList();
With a recent change in data I now need to also reference the SecondaryData but due to the number of records really need this to load Eagerly instead of Lazy. (Lazy loading during the loop results in thousands of DB calls)
I have looked at using the "Include" method on surveydata as well as casting the initial query as an ObjectQuery and doing the Include off that.
The first method doesn't eager load and the second method seems to always return a null object as a result.
Is there a method to Eager load the SecondaryData for SurveyData or should I be looking at a different approach all together.
My only restriction on this is that I can't go up to EF5 because of a limitation we have on .Net 4.5
Any assistance would be greatly appreciated.
Thank you.
You could try to project into an anonymous object first and use also SecondaryData in that projection, materialize this result and then project again into your final result object. Automatic Relationship Fixup that the EF context provides should populate the navigation property surveyData.SecondaryData of your ComparisonWithData object (as long as you don't disable change tracking in your query):
var data = (( // ... part up to select unchanged ...
select new // anonymous object
{
compgrp = compgrp,
surveydata = surveydata,
secondarydata = surveydata.SecondaryData
}
)).AsEnumerable();
// part until here is DB query, the rest from here is query in memory
List<ComparisonWithData> comparisonwithdata =
(from d in data
select new ComparisonWithData
{
compgrp = d.compgrp,
surveydata = d.surveydata
}
)).ToList();

Adding a index to collection using EF 4.1 and XAML (For a highscore table)

I have a webservice I call from a WP7 app. I get a list of high scores in a table (name/score).. What is the simpliest way to add a 3rd column on the far left which is simply the row?
Do I need to add a property to the entity? Is there someway to get the row #?
I tried these things below with no success..
[OperationContract]
public List<DMHighScore> GetScores()
{
using (var db = new DMModelContainer())
{
// return db.DMHighScores.ToList();
var collOrderedHighScoreItem = (from o in db.DMHighScores
orderby o.UserScore ascending
select new
{
o.UserName,
o.UserScore
}).Take(20);
var collOrderedHighScoreItem2 = collOrderedHighScoreItem.AsEnumerable().Select((x, i) => new DMHighScoreDTO
{
UserName = x.UserName,
UserScore = x.UserScore
}).ToList();
}
}
[DataContract]
public class DMHighScoreDTO
{
int Rank;
string UserName;
string UserScore;
}
So lets assume you want to load top 100 users in leaderboard and you want to have their rank included:
[OperationContract]
public List<ScoreDto> GetTop100()
{
// Linq to entities query
var query = (from u from context.Users
order by u.Score
select new
{
u.Name,
u.Score
}).Take(100);
// Linq to objects query from working on 100 records loaded from DB
// Select with index doesn't work in linq to entities
var data = query.AsEnumerable().Select((x, i) => new ScoreDto
{
Rank = i + 1,
Name = x.Name,
Score = x.Score
}).ToList();
return data;
}
what will the row number be used for? if this is for ordering might I suggest adding a column named Order, then map the column to your entity.
if you require a row index, you could also call the .ToList() on the query and fetch the index locations for each entity.
Edit:
you could add the Rank property and set it to Ignore. This will enable you to go through the collection set the rank with a simple for loop. This will also not be persisted in the database. It will also not have any required columns in the database.
It does add an extra iteration.
the other way to go about it. This would be to add the rank number in the generated UI and not in the data collection being used to bind.

How to access columns from an IQueryable when dynamically constructed?

I am using the System.Linq.Data library provided here - http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
I have the following query which works great and returns an Iqueryable
IQueryable customer =
ctx.Customers.Where(cust => true).Select("new("Name,Address")");
However, how do I access these returned columns? I cannot access them using a lambda expression as follows:
var test = customer.Where(cust=>cust.Name == "Mike").First();
"cust.Name" in the above case cannot be resolved. It does not exist in the list of methods/properties for "cust".
Am i assuming something wrong here. I understand that I am working with an anonymous type. Do I have to create a DTO in this case?
For any IQueryable you have property called ElementType.
You can use it to get the properties as explained below
IQueryable query = from t in db.Cities
selec new
{
Id = t.Id,
CityName = t.Name
};
if(query!=null)
{
Type elementType = query.ElementType;
foreach(PropertyInfo pi in elementType.GetProperties())
{
}
}
Try foreach loop:
var a = _context.SENDERS.Select(x=>new { Address=x.ADDRESS, Company=x.COMPANY });
foreach(var obj in a)
{
Console.WriteLine(obj.Address);
Console.WriteLine(obj.Company);
}