Have a page that shows 1 restaurant and below is the list of 5 suggested restaurants = objects (random list of restaurants with various properties such as the name of the restaurant, cusineType, rating, location). Returning back 5 random objects.
var random = new Random(); var results = restaurants.Where(restaurant => restaurant.cusineType == "Sushi").OrderBy(x => random.Next()).Take(5).ToList();
With the current setup, it returns 5 random restaurants, but:
it can return in the list the same restaurant as the one loaded on the page
it can return 2 same objects in the list
How to make it return only unique 5 random objects?
you can use skip() and take() on the list and get a random entities.
var distributes = _home.GetDistributeCenter().ToList();
Random rand = new Random();
int toSkip = rand.Next(0, distributes.Count - 6);
var randomlist = distributes.Skip(toSkip).Take(5).ToList();
Related
I'm working on an ASP.NET MVC application with Entity Framework 6 and a SQL Server database.
I'm trying to shuffle the results of a query by adding a SortingCode which I'd like to assign a value based on the current SessionId, so that every time the returned rows are shuffled without affecting the pagination. SortingCode in this attempt is a string, but it can be any type, as long as it allows me to get shuffled results. I have something like this:
var sessionId = Session.SessionID.GetHashCode();
var rnd = new Random(sessionId);
var query = (from l in _context.Adverts
select new AdvertSummary
{
Id = l.Id,
Title = l.Title,
Description = l.Description,
SortingCode = l.Title.OrderBy(x => rnd.Next()).ToString(),
});
The IQueryable result is then converted into a list later on in my code with:
var pagedResults = query.Skip(skip).Take(pageSize).ToList();
The above attempt with the Random class doesn't work, and results in an error
DbExpressionBinding requires an input expression with a collection ResultType
Is there anything that I can do to get shuffled results?
I would suggest to use SqlFunctions.Checksum for such task. SortingCode will be nearly close to the seeded Random.
var sessionId = Session.SessionID;
var query =
from l in _context.Adverts
select new AdvertSummary
{
Id = l.Id,
Title = l.Title,
Description = l.Description,
SortingCode = SqlFunctions.Checksum(sessionId, l.Title)
};
var pagedResults = query
.OrderBy(x => x.SortingCode)
.ThenBy(x => x.Id)
.Skip(skip)
.Take(pageSize)
.ToList();
I have a bunch of records that are sorted RANDOMLY, like so:
var entries = DataContext.Entries.OrderBy(e => Random());
The Random function returns a randomly-generated GUID, thereby ordering the records in a random manner. Now my problem is paging. In MVC, I have a List action for the Entry controller that lists the entries:
public class EntryController : Controller
{
public ActionResult List(int page)
{
int pageSize = 10;
var entries = DataContext.Entries.OrderBy(e => Random()).Skip((page - 1) * pageSize).Take(pageSize);
ViewData["entries"] = entries;
return View();
}
}
My problem here is that whenever I go from one page to another page, the entries are REARRANGED ANEW. So when I go to page 1 (step 1), then go to page 2 (step 2), then back to page 1 (step 3), the entries that were shown in the step 1 are different from those shown in step 3. I absolutely need to have the records arranged randomly the first time around, but not in the subsequent look ups.
Any ideas on how best to address this problem?
Because each time you invoke the action the randomness occurs all over again to the whole records before paging, what you need to do is:
Order the records randomly as you want it.
Cache the result.
Fetch the cache every time the action is invoked while applying paging.
public ActionResult List(int page)
{
var dataSource = CacheContext["RandomRecords"];
if(dataSource == null){
dataSource = DataContext.Entries.OrderBy(e => Random());
}
int pageSize = 10;
var entries = dataSource.Skip((page - 1) * pageSize).Take(pageSize);
ViewData["entries"] = entries;
return View();
}
Add a column named sortOrder, being an int.
Do not forget to add a non-unique index on it or sorting on it will be suboptimal.
Put a number there, increased from record to record, not in the same order than your id or an order that would sort the records alphabetically.
Then
dataSource = DataContext.Entries.OrderBy(e => e.sortOrder);
Guids will be slower to sort on, but you can alternatively use a guid column for the task. Every now and then (once per night), you can loop through all records to put new values in the sortOrder column so people will not recognize the order.
You can add following SQL code to get products, you only need to generate some random number and store it into the session or cache and get product again..
DECLARE #NumberOfProductsInDatabase INT
DECLARE #RandomNumber VARCHAR(10)
SET #NumberOfProductsInDatabase = (SELECT COUNT(*) FROM Product)
SET #RandomNumber = '45'
SELECT CAST(100000 * SQRT(EXP(COS(p.SellerId + #RandomNumber))) AS INT) % #NumberOfProductsInDatabase AS RandomProductNr,
p.Id,p.Name,pv.Price,pv.SalePrice
FROM Product p,ProductVariant pv
WHERE pv.ProductId = p.Id
ORDER BY RandomProductNr
I've been racking by brain all night (again) looking to get the total count of each set of unique items in a list. I was able to get the unique list items. But I can't seem to figure out how to get the count of each group of unique items. Please tell me if this makes sense. Below's my code:
List<string> categories = new List<string>();
foreach (var item in Model)
{
categories.Add(item.Category);
}
IEnumerable<string> distinctCategories = categories.Distinct();
foreach (string category in distinctCategories)
{
#category #category.Count()
}
As you can see, I have a link displayed for each unique item in my Model's "Category" property (Item.Category). Where you see the category count at the end of the link it actually displays the number of characters in the category (such as the number 5 for the category "Rings"). But I really want the number to represent the number of times the category "Rings", for example, is found in the Model's Categories property.
Please help
To get the count, you need to use a GroupBy instead of Distinct:
var distinctCategories =
categories.GroupBy(x => x)
.Select(g => new { Name = g.Key, ItemsCount = g.Count() });
foreach (var category in distinctCategories)
{
#category.Name #category.ItemsCount
}
I have created a set of search results, and I wish to create a filter of available cats, with the number of results within that filter. however I get the most strangest error when trying to do this.
Unable to create a constant value of type 'NAMESPACE.Models.Products'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
this is the code i have tried:
var cats = (from p in ctx1.SubCategories
where myCats.Contains(p.subCategoryId) && p.enabled
select new
AvailableSubCats
{
CategoryName = p.subCategoryName,
Id = p.subCategoryId,
TotalItems = model.Count(x => x.subCategoryId == p.subCategoryId)
}).Distinct();
Products is the object that is called model on the line of totalItems.
I have also tried this:
var cats = from c in ctx1.SubCategories
join p in model on c.subCategoryId equals p.subCategorySubId
group p by c.subCategoryName
into g
select new
AvailableSubCats
{
CategoryName = g.Key,
Id = 0,
TotalItems = g.Count()
};
with the same error, and dont like this because i dont know how to get the name of the category and its ID.
help much appreciated.
thanks
p.s I am using Entity framework 4.1, .net 4 and MVC 3, mysql
in short i am trying to run this in linq, but were the the products side is already a result
select c.*, (select count(productId) from Products where Products.subCategoryId = c.subCategoryId) as counter from SubCategories c
You could try turning your list of products into a list of subCategoryId's so EF can understand it. Something like:
var subCategoryIds = model.Select(m => m.subCategoryId);
var cats = (from p in ctx1.SubCategories
ctx1.SubCategories
where myCats.Contains(p.subCategoryId) && p.enabled
select new
AvailableSubCats
{
CategoryName = p.subCategoryName,
Id = p.subCategoryId,
TotalItems = subCategoryIds.Count(x => x == p.subCategoryId)
}).Distinct();
The following code doesn't seem to get the correct count.....
var materials = consRepository.FindAllMaterials().AsQueryable();
int count = materials.Count();
Is it the way to do it.... Here is my repository which fetches records...
public IQueryable<MaterialsObj> FindAllMaterials()
{
var materials = from m in db.Materials
join Mt in db.MeasurementTypes on m.MeasurementTypeId equals Mt.Id
where m.Is_Deleted == 0
select new MaterialsObj()
{
Id = Convert.ToInt64(m.Mat_id),
Mat_Name = m.Mat_Name,
Mes_Name = Mt.Name,
};
return materials;
}
Edit:
when i use this,
var materials = consRepository.FindAllMaterials().AsQueryable();
return View("Materials", materials);
I get 18 rows in my table... So y cant i get the count as 18 instead it gives 12
Ans:
Breakpoint doesn't seem produce me the result but response.Write(count) did...
This should get the correct count:
int count = consRepository.FindAllMaterials().Count();
How are you iterating through the model in your view?
Is it possible that you are displaying duplicate entries?
Is it possible that you're not joining on the correct columns? The only reason I ask is that your id columns aren't consistently named in each class. For Materials you are using Mat_id, but in MeasurementTypes you are using simply, Id. It makes me wonder if you're trying to join a natural key value against an artificial primary key instead of the corresponding natural foreign key.