ORDER BY NEWID in LINQ and bind to Repeater control - asp.net

Morning,
I would like to know how to write the following SQL statement in LINQ.
SELECT TOP 6 * FROM Questions
ORDER BY NEWID()
I would also like to know, how i could bind this to a asp.net repeater control to display the 6 questions.
Many thanks :)

The Linq style would be
Questions.OrderBy(q=>Guid.NewGuid()).Take(6)
then you attach that to a repeater by setting its DataSource property to the above, and calling the DataBind method.

You would have to be able to invoke the NEWID() function to generate your random guids. To do so, you could take some hints here and first create a pseudo-method mapped to the NEWID() function on your data context.
[System.Data.Linq.Mapping.Function(Name="NEWID", IsComposable=true)]
public Guid NewId()
{
throw new NotImplementedException();
}
Once that is set, you could then write your query to use this function:
var query = dc.Questions
.OrderBy(question => dc.NewId())
.Take(6);
You can inspect the SQL query generated for this and it should match.

Questions.OrderBy(q=>Sql.NewGuid()).Take(6)
This will invoke the NEWID() in SQL statement.

(from db in context.Questions
order by Guid.NewGuid()
select db).Take(6);

I know answer is already selected, but still I'm adding my way to achieve this. Faced same situation today and tried couple of ways, used questions.OrderBy(q => Guid.NewGuid()).ToList() and couple of more suggestions. Later I thought to add a new field string RandomOrder in view model and assigned Guid.NewGuid().ToString() in loop and then used questions.OrderBy(i => i.RandomOrder).ToList() and this worked great.
I had requirement to shuffle questions if author selected option shuffleAlways while creating assessment. If not then sort on regular sorting order. Here is complete solution:
private List<AssessmentQuestionsViewModel> LoadAllQuestions(string assessmentId, bool shuffleQuestions)
{
List<AssessmentQuestionsViewModel> questions = new List<AssessmentQuestionsViewModel>();
var items = assessmentQuestionRepository.GetAll().Where(i => i.AssessmentId == assessmentId).ToList();
foreach (var item in items)
{
questions.Add(new AssessmentQuestionsViewModel
{
Id = item.Id,
AssessmentId = item.AssessmentId,
QuestionText = item.QuestionText,
HintText = item.HintText,
QuestionType = item.QuestionType,
MaxMarks = item.MaxMarks,
SortOrder = item.SortOrder,
RandomOrder = Guid.NewGuid().ToString(),
Answers = LoadAllAnswers(item.Id)
});
}
if (shuffleQuestions)
{
questions = questions.OrderBy(i => i.RandomOrder).ToList();
}
else
{
questions = questions.OrderBy(i => i.SortOrder).ToList();
}
return questions;
}
And this worked like charm. Hope this help others.

I assume you are using ORDER BY NEWID() as a way to select random data from your questions? If so, you should avoid using NEWID() (or it's LINQ equivalent), causes tons a new guid to be generated for every record in your table. On a large dataset, that's devestating.
Instead, see Linq Orderby random ThreadSafe for use in ASP.NET for an optimized solution to random sorts. Then just add a take operator and your set.
Random random = new Random();
int seed = random.Next();
var RandomQuestions = Questions.OrderBy( s => (~(s.Shuffle & seed)) & (s.Shuffle | seed)); // ^ seed);
return RandomQuestions.Take(6);

Related

What should be the type parameter for List<T> and .Query<T> for joined table?

I am very new to Xamarin Forms and SQLite. I have the following method that returns a list from two joined tables. My problem is I don't know what is the right type parameter the List<T> and .Query<> should have to be able to get the values of both Category and Phrase table. Can anyone enlighten me on this one?
public List<?> GetWordsByCategory(int category)
{
lock (locker)
{
var words = databaseConnection
.Query<?>("Select Category.*, Phrase.*
From Category
Join Phrase on Category.Id = Phrase.CategoryId
Where Category.Id = 1")
.ToList();
return words;
}
}
I have tried List<Category> but would only return the properties of the Category table likewise List<Phrase>
You can return a dynamic or create a new class.
But I would suggest you to use the SQLite.Net PCL which is a wrapper around SQL and which enables you to query database like EF using linq and lamda than string queries.
You can look into this similar question which should help you.

how to use multiple order by in LINQ?

I want to use multiple order by in my query, and i am using LINQ.i am new to LINQ, i have tried the examples given on stackoverflow. but i dont know why these are not working for me , i am sure i am wrong some where. below is my situation.
I got a project in which created using LINQ. I have little task to set order of column. Actually what is my task there is a column created date by which its ordering now. Now i want to use Createddate as well a sortOrder column for ordering.Below is code used for it:
Code in page load method
ViewState["SortDirection"] = "desc";
ViewState["SortColumn"] = "createddate";
BindAllTopics(ViewState["SortDirection"].ToString(), ViewState["SortColumn"].ToString());
And my BindAllTopic Method is as bellow:
protected void BindAllTopics(string SortType, string SortColumn)
{
var LstTopics = (from topic in Dbobj.T_topic select topic).ToList();
if (LstTopics.Count() > 0)
{
if (SortType == "ASC")
{
LstTopics = LstTopics.OrderBy(q => q.Name).ToList();
}
else
{
LstTopics = LstTopics.OrderByDescending(q => q.Name).ThenBy(q => q.SortOrder).ToList();
}
GrdTopics.DataSource = LstTopics.ToList();
GrdTopics.PageSize = 25;
GrdTopics.DataBind();
}
else
{
GrdTopics.DataSource = null;
GrdTopics.DataBind();
lblMsg.DisplayMessage(StatusMessages.InfoMessage, "No Topics Found.");
}
}
I want to sort it firstly by sortorder which is of int type and then by Createddate.
Please help me..
you can add one more ThenBy() in trail
LstTopics.OrderByDescending(q => q.Name).ThenBy(q => q.SortOrder).ThenBy(m=>m.date)
If you do not want to use Dynamic Linq the following see Marc Gravell's answer below
stackoverflow:Dynamic Linq OrderBy
After correction you can achieve this by Dynamic Linq
LstTopics = LstTopics.OrderBy(SortColumn + " " + SortType);)

Returning a column from a linked table in LINQ to SQL

My problem is that I am trying to return a simple query that contains an object Story. The Story object has a UserId in the table which links to aspnet_users' UserId column. I have created a partial class for Story that adds the UserName property since it does not exist in the table itself.
The following query gets all stories; however, a pagination helper takes the query and returns only what's necessary once this is passed back to the controller.
public IQueryable<Story> FindAllStories(){
var stories = (from s in db.Stories
orderby s.DateEntered descending
select new Story
{
Title = s.Title,
StoryContent = s.StoryContent,
DateEntered = s.DateEntered,
DateUpdated = s.DateUpdated,
UserName = s.aspnet_User.UserName
}
);
return stories;
}
When the helper does a .count() on the source it bombs with the following exception:
"Explicit construction of entity type 'MyWebsite.Models.Story' in query is not allowed."
Any ideas? It's not a problem with the helper because I had this working when I simply had the UserName inside the Story table. And on a side note - any book recommendations for getting up to speed on LINQ to SQL? It's really kicking my butt. Thanks.
The problem is precisely what it tells you: you're not allowed to use new Story as the result of your query. Use an anonymous type instead (by omitting Story after new). If you still want Story, you can remap it later in LINQ to Objects:
var stories = from s in db.Stories
orderby s.DateEntered descending
select new
{
Title = s.Title,
StoryContent = s.StoryContent,
DateEntered = s.DateEntered,
DateUpdated = s.DateUpdated,
UserName = s.aspnet_User.UserName
};
stories = from s in stories.AsEnumerable() // L2O
select new Story
{
Title = s.Title,
StoryContent = s.StoryContent,
...
};
If you really need to return an IQueryable from your method and still need the Username of the user you can use DataContext.LoadOptions to eagerload your aspnet_user objects.
See this example.

How to delete in linq to sql?

I am very new to linq to sql and I am not sure how to actually delete a record.
So I been looking at this tutorial
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
So for Update they have
NorthwindDataContext db = new NorthwindDataContext();
Product product = db.Products.Single(p => p.ProductName == "Toy 1");
product.UnitPrice == 99;
product.UnitsInStock = 5;
db.SubmitChanges();
For delete they have
NorthwindDataContext db = new NorthwindDataContext();
var toyProducts = from p in db.Producsts
where p.ProductName.Contains("Toy")
select p;
db.Products.RemoveAll(toyProducts);
db.SubmitChanges();
So do I have to query every time, to get the record in order to delete that record? Like I can sort of see doing this with update since you need to give it a record which to update first and then make the changes so I understand the querying part but not with delete.
Like can't you just send in what you want to delete and it goes and deletes it? why do you have to first get it and then tell it to be deleted?
Is that not 2 hits on the database?
Also I have foreign key relationship that I am trying to get to work. So I have this
public ViewResult(string param1, string param2)
{
Table A = new Table A
A.Field1 = param1;
A.Field2 = param2;
Delete(A);
}
private void Delete(Table A)
{
DbContext.A.DeleteAllOnsubmit(A.TableB);
DbContext.A.DeleteAllOnSubmit(A.TableC);
DbContext.A.DeleteOnSubmit(A);
}
So this fails it comes up with this message "Cannot remove an entity that has not been attached."
So I can see why the first 2 lines would fail in the delete method, since I made a new object and their is nothing in the object that has any information about TableB and TableC.
I however can't see why the last line still fails even if the 2 other lines where not there.
Like how I thought it would work it would take my Table A class object that I passed in and look through the table for that information contained in it. It does not seem to be the case though.
So do I first have to take the information out and then do a query to get it and then delete it, like in the example?
Also what is the difference between removeAll() and say DeleteAllOnSubmit().
Like I said I am new to linq to sql and have not been able to sit down and read a book on it due to time constraints. Once I have more time I will read through a book probably.
Thanks
You have several questions in your one question, but I will start with the simplest, about attaching, if you already have the primary key. If you don't have the primary key then I have always just done a fetch then a delete, but, whenever I do a fetch I tend to store the primary key for updates and deletes.
It will delete off of the primary key, but if you have that then just attach as I do below and call delete. I don't pass around the object needed by DLINQ as I want to be able to change it if I want, so I pass in a different User object and just pull the PK from the business class and put it into the DAO class.
var db = new MeatRequestDataContext();
if (input.UserID > 0)
{
entity = new User()
{
UserID = input.UserID
};
db.Users.Attach(entity);
db.Users.DeleteOnSubmit(entity);
}
this is a simple way to delete row from table by linq query.may be it helps .
var summary_delete = database.summeries.Find(id);
var delete = database.summeries.Remove(summary_delete);
database.SaveChanges();
reference : http://mvc4asp.blogspot.in/2013/09/how-to-delete-table-row-in-sql-database.html
Inserted_LINQDataContext db = new Inserted_LINQDataContext();
Item itm = new Item();
int ID = Convert.ToInt32(TextBox1.Text);
var DeleteID = from d in db.Items
where d.id == ID
select d;
db.Items.DeleteAllOnSubmit(DeleteID);
db.SubmitChanges();
Label2.Text = "Record deleted Successfully.";
TextBox1.Text = "";
where Item is Table name, Linserted_LINQDataContext is your Linq DB name, id is the Column name in Item table. Items is the alias name of Item table in linq.
SupportDataDataContext Retrive = new SupportDataDataContext();
// SupportDataDataContext delete = new SupportDataDataContext();
Topic res = Retrive.GetTable<Topic>().Single(t => t.ID == topicID);
if (res != null)
{
Retrive.Topics.DeleteOnSubmit(res);
Retrive.SubmitChanges(ConflictMode.ContinueOnConflict);
}
I know the question is old but this may be useful to someone:
"YourDataContext" dc = new "yourDataContext";
"YourTable" element = dc."YourTable".First(a => a.Id == 12345);
dc."YourTable".DeleteOnSubmit(element);
dc.SubmitChanges();

LINQ to SQL - How to select specific columns and return strongly typed list

I'm trying to use LINQ to SQL to select a few specific columns from a table and return the result as a strongly typed list of objects.
For Example:
var result = (from a in DataContext.Persons
where a.Age > 18
select new Person
{
Name = a.Name,
Age = a.Age
}
).ToList();
Any help would be greatly appreciated.
It builds fine, but when I run it, I get the error. Explicit construction of entity type MyEntity in query is not allowed.
Basically you are doing it the right way. However, you should use an instance of the DataContext for querying (it's not obvious that DataContext is an instance or the type name from your query):
var result = (from a in new DataContext().Persons
where a.Age > 18
select new Person { Name = a.Name, Age = a.Age }).ToList();
Apparently, the Person class is your LINQ to SQL generated entity class. You should create your own class if you only want some of the columns:
class PersonInformation {
public string Name {get;set;}
public int Age {get;set;}
}
var result = (from a in new DataContext().Persons
where a.Age > 18
select new PersonInformation { Name = a.Name, Age = a.Age }).ToList();
You can freely swap var with List<PersonInformation> here without affecting anything (as this is what the compiler does).
Otherwise, if you are working locally with the query, I suggest considering an anonymous type:
var result = (from a in new DataContext().Persons
where a.Age > 18
select new { a.Name, a.Age }).ToList();
Note that in all of these cases, the result is statically typed (it's type is known at compile time). The latter type is a List of a compiler generated anonymous class similar to the PersonInformation class I wrote above. As of C# 3.0, there's no dynamic typing in the language.
UPDATE:
If you really want to return a List<Person> (which might or might not be the best thing to do), you can do this:
var result = from a in new DataContext().Persons
where a.Age > 18
select new { a.Name, a.Age };
List<Person> list = result.AsEnumerable()
.Select(o => new Person {
Name = o.Name,
Age = o.Age
}).ToList();
You can merge the above statements too, but I separated them for clarity.
The issue was in fact that one of the properties was a relation to another table. I changed my LINQ query so that it could get the same data from a different method without needing to load the entire table.
Thank you all for your help!
Make a call to the DB searching with myid (Id of the row) and get back specific columns:
var columns = db.Notifications
.Where(x => x.Id == myid)
.Select(n => new { n.NotificationTitle,
n.NotificationDescription,
n.NotificationOrder });

Resources