Return multiple results from SQL Server - c#

Currently I can input a product name into a textbox and search that name in the SQL Server database. And return ONLY a single unique row. This works fine. But when I search for e.g. Bike. I need Blue bike AND Red Bike to be returned.
I currently have:
public List<Product> GetProductByName(string name)
{
List <Product> productList = new List<Product>();
using (var context = _dbContextFactory.CreateDbContext())
{
productList.Add(context.Product.SingleOrDefault(x => x.ProductName == name));
return productList;
}
}
Currently I'm getting a System.InvalidOperationException: 'Sequence contains more than one element'.

Don't use SingleOrDefault if you're expecting multiple rows. Perhaps instead:
using (var context = _dbContextFactory.CreateDbContext())
{
return context.Product.Where(x => x.ProductName == name).ToList();
}

you can use Contains in Where:
using (var context = _dbContextFactory.CreateDbContext())
{
return context.Product.Where(x => x.ProductName.Contains(name)).ToList();
}

public List<Product> GetProductByName(string name)
{
List<Product> productList = new List<Product>();
using (var context = _dbContextFactory.CreateDbContext())
{
productList = context.Product.Where(x => x.ProductName == name).ToList();
return productList;
}
}

Related

LINQ Where query with object list

I have a list of objects ListA with property Id and I have to make a query in a table that has a column Id and find the rows that the ids are the same. How exactly can I achieve that with a single query and not a foreach loop of listA?
Thank you for your time
foreach(var object in listA)
{
context.Table.Where(x => x.id == object.Id)....
}
Looks like you want to return all rows from the table that have an ID contained in the list of objects with the same ID. The following will achieve this. I can modify my answer to suit your need. Just let me know if you are looking for something slightly different.
void Main()
{
var listA = new List<A> { new A { Id = 1 }, new A { Id = 4 } };
var results = context.Table
.Where(t => listA.Select(l => l.Id).Contains(t.Id))
}
public class A
{
public int Id { get; set; }
}

How to return two specific columns from database using LINQ?

I have table called Asset. It has lot of columns. I only want to select two of them and use them separately.
Both of these columns are strings.
Linq query :
public static List<string> GetAssetIdsWithNames()
{
using (var db = DbManager.Get())
{
var result = db.Assets.SelectMany(i=> new[] { i.AssetName, i.AssetId }).Distinct().ToList();
return result;
}
}
Where I want to use them :
var assetList = AssetManager.GetAssetIdsWithNames();
//CURRENCYBOX IS A DROPDOWN
CurrencyBox.DataSource = assetList;
CurrencyBox.DataBind();
foreach (var item in assetList)
{
CurrencyBox.DataValueField = //asset id goes here
CurrencyBox.DataTextField =//asset name goes here
break;
}
You cannot access the anonymous type outside of the local scope.
Anonymous types can only be returned as Object outside their local scope and their properties inspected via reflection.
So in this scenario, you are likely better off to use a typed data contract and map from your Asset entity instead and then access it from your calling method.
Your use of SelectMany seems odd too, you probably are after Select instead.
public class AssetDto
{
public string Name { get;set; }
public string Id { get; set; }
}
public static List<AssetDto> GetAssetIdsWithNames()
{
using (var db = DbManager.Get())
{
var result = db.Assets.Select(i=> new AssetDto { Name = i.AssetName, Id = i.AssetId }).ToList();
return result;
}
}
You could use named value tuples for that so you don't need to create an extra class
public static List<(string Name, int Id)> GetAssetWithIds()
{
using (var db = DbManager.Get())
{
var result = db.Assets
.Select(a => new { a.AssetName, a.AssetId })
.Distinct().AsEnumerable()
.Select(a => (a.AssetName, a.AssetId))
.ToList();
return result;
}
}
You will need to add System.ValueTuple

Asp.net 5 WebApi 2.0 partial response

I'm working on LinQ to Entity,
Here is my working code:
var products = from p in AppContext.Products
join ... //joins tables
where ... //conditions
select p;
var result = products.OrderBy(p => p.Name);
//Move it to custom format.
return result.Select(p => new
{
p.Id,
p.Name,
p.Description,
...
/*This looks ugly and need to be moved out to somewhere else*/
Categories = FindCategories(p.Id, true),
MetaData = AppContext.ProductMetas.Where(pm => pm.ProductId == p.Id),
Photos = AppContext.ProductPhotos.Where(pp => pp.ProductId == p.Id)
}).Skip(skip).Take(take);
However, I would like to move 'return new...' part into somewhere else (better inject asp.net api handler when transform object to json). For example:
//GetAll()
...
var products = from ... in ... select p;
return products;
//How to register some handler
var results = new List<object>();
foreach (var product in resultSet) {
//merge objects into result set
results.Add(new {/*Merge properties together*/})
}
But I don't know how to do this. Anyone familiar with this, please help.
I’m not quite clear on whether you need assistance with the actual mapping of the object in Linq to Entities or how to add this logic to an ASP.NET 5 route, I am assuming it is the latter.
One approach would be to create a DTO, that will contain the entity and relation data you require, like so:
public class ProductDTO
{
public int Id {get;set;}
public string Name {get;set;}
public List<Category> Categories {get;set;}
...
}
You will then need to create a controller to handle the request:
[Route("api/[controller]")]
public class ProductController : Controller
{
[HttpGet]
public IActionResult GetAll()
{
var products = //..make call to service or query to get products..
var results = new List<ProductDTO>();
foreach (var product in products)
{
// merge objects into new ProductDTO collection
results.Add(a=> new ProductDTO() {Id = a.Id, Name = a.Name ...});
}
return new JsonResult(values);
}
}

Explicit construction of entity type 'Artist' in query is not allowed

Compile just fine but execution fail with the error in the title.
ArtistService.cs
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new Artist()
{
Id = artist.Id,
Artist_name = Artist.Artist_name
}).ToList(); <=== error happened here
}
}
}
code Behind
private List<ArtistServiceReference.Artist> ArtistDetail()
{
ArtistServiceReference.ArtistServiceClient client = new
ArtistServiceReference.ArtistServiceClient();
ArtistServiceReference.Artist[] artists = client.ArtistDetail();
return artists.ToList();
I want to move the Artist List to a DropdownList.
The error is happening in the ArtistService.cs at the end {).ToList();
Any explanation on how to fix this issue? Thanks
I based my code on this example and this example is working fine.
example code MyService.cs
public class MyService : IMyService
{
public List<Task> GetTasks()
{
using (TasksDataContext db = new TasksDataContext())
{
return (from task in db.TasksLists
select new Task()
{
Id = task.taskId,
Name = task.taskName,
}).ToList();
}
}
}
Example default.aspx.cs
private List<TaskService.Task> GetTasks()
{
TaskService.MyServiceClient client = new TaskService.MyServiceClient();
TaskService.Task[] tasks = client.GetTasks();
return tasks.ToList();
}
I don't understand why this example will work and not mine. The only difference was this example is returning to a gridview and I want to return to a dropdownlist.
Linq to Entities cannot translate the Artist object creation into SQL code (really, what is this supposed to look like?). Linq to Entities can only execute SQL queries and map returned fields to some entity to which it knows how to map (i.e. your DbSet entities). So, you need to execute the query first and then create the Artist entities locally:
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new { // select only columns you need
artist.Id,
artist.Artist_name
})
.AsEnumerable() // execute query
.Select(x => new Artist { // create instance of class
Id = x.Id,
Artist_name = x.Artist_name
})
.ToList();
}
}
}
BTW it looks like you have Artist entities in your Artists DbSet. Why not simply return
return db.Artists.ToList();

Method for removing items from List

Related to this: Adding new items dynamically to IQueryable hard-coded fake repository
How could I build the method for the following class, which would remove items from the list based on the value of one of its fields?
public class FakeProductsRepository
{
private readonly List<Product> fakeProducts = new List<Product>
{
new Product { ProductID = "xxx", Description = "xxx", Price = 1000 },
new Product { ProductID = "yyy", Description = "xxx", Price = 2000 },
new Product { ProductID = "zzz", Description = "xxx", Price = 3000 },
};
public void AddProduct(string productID, string description, int price)
{
fakeProducts.Add(new Product
{
ProductID = productID,
Description = description,
Price = price,
});
}
public void RemoveProduct(string productID)
{
????????
//How to remove the item from the fakeProducts List where ProductID == productID?
}
public IQueryable<Product> Products
{
get { return fakeProducts.AsQueryable(); }
}
}
The problem method is pointed out with "???????" and the comment string.
In general, for a collection I'd use this code:
var productsToRemove = fakeProducts.Where(p => p.ProductID == productID).ToList();
foreach(var product in productsToRemove)
{
fakeProducts.Remove(product);
}
Don't forget the ToList(), or you can get an InvalidOperationException saying "Collection was modified".
Update (thanks to linuxuser27):
But List<T> also has a special method, taking Predicate<T>:
fakeProducts.RemoveAll(product => product.ProductID == productID);
Try using LINQ with the where clause. Note you need .NET 3.5.
var reducedProducts = from r in fakeProducts
where r.ProductID != productID
select r;
This will give you a reduced collection.
You could also use the RemoveAll() method, which takes a predicate but modifies the current collection.
fakeProducts.RemoveAll(delegate (Product r) { return r.ProductID != productID; });
If looking up items by product ID is a common operation, consider replacing the list with a dictionary keyed by the product ID.
If, however, you want to keep the List as the data structure, then just loop over it (this assumes that there's only one product with a given ProductID):
foreach(Product p in fakeProducts)
{
if(p.ProductId == productID)
{
fakeProducts.remove(p);
break;
}
}

Categories

Resources