Get List Data of selected Column from Table - asp.net-core-mvc

I want to get data of selected columns from a table and return that data in repository class. But my query does not return any data.
My Code is:
public IQueryable<BusinessProfile> GetBusinessProfileAddress()
{
var y = _db.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new
{
x.ID,
x.Address.StreetName,
x.Address.Number,
x.Address.Complement,
x.Address.PostalCode,
x.Address.Neighborhood,
x.Address.City,
x.Address.State
});
var d=from a in BusinessProfile select a.
return y; ;
}
Note: Here "return y" is in showing error.

This code won't even build because you haven't finished this query: var d=from a in BusinessProfile select a., but, you are not using the d variable at all so you should remove the whole var d=from a in BusinessProfile select a. line. And you don't need 2 semicolons after y. So, your code should look like this:
public IQueryable GetBusinessProfileAddress() {
var y = _db.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new
{
x.ID,
x.Address.StreetName,
x.Address.Number,
x.Address.Complement,
x.Address.PostalCode,
x.Address.Neighborhood,
x.Address.City,
x.Address.State
});
return y;
}

For your current code, you will get error like
Cannot implicitly convert type 'System.Linq.IQueryable<>' to 'System.Linq.IQueryable'. An explicit conversion exists
If you want to return the new type, you may consider define a new model and change BusinessProfile.
public IQueryable<BusinessProfileVM> GetBusinessProfileAddress()
{
var y = _appDbContext.Set<BusinessProfile>().Where(x => x.Deleted == false).Select(x => new BusinessProfileVM
{
Id = x.Id,
StreetName = x.Address.StreetName,
});
return y;
}
public class BusinessProfileVM
{
public int Id { get; set; }
public string StreetName { get; set; }
}

Related

How to select multiple class properties in LINQ Expression?

If I have a class like this
`
class Person
{
public string First;
public string Last;
public bool IsMarried;
public int Age;
}`
Then how can I write a LINQ Expression where I could select properties of a Person. I want to do something like this (user can enter 1..n properties)
SelectData<Person>(x=>x.First, x.Last,x.Age);
What would be the input expression of my SelectData function ?
SelectData(Expression<Func<TEntity, List<string>>> selector); ?
EDIT
In my SelectData function I want to extract property names and then generate SELECT clause of my SQL Query dynamically.
SOLUTION
Ok, so what I have done is to have my SelectData as
public IEnumerable<TEntity> SelectData(Expression<Func<TEntity, object>> expression)
{
NewExpression body = (NewExpression)expression.Body;
List<string> columns = new List<string>();
foreach(var arg in body.Arguments)
{
var exp = (MemberExpression)arg;
columns.Add(exp.Member.Name);
}
//build query
And to use it I call it like this
ccc<Person>().SelectData(x => new { x.First, x.Last, x.Age });
Hopefully it would help someone who is looking :)
Thanks,
IY
I think it would be better to use delegates instead of Reflection. Apart from the fact that delegates will be faster, the compiler will complain if you try to fetch property values that do not exist. With reflection you won't find errors until run time.
Luckily there is already something like that. it is implemented as an extension function of IEnumerable, and it is called Select (irony intended)
I think you want something like this:
I have a sequence of Persons, and I want you to create a Linq
statement that returns per Person a new object that contains the
properties First and Last.
Or:
I have a sequence of Persns and I want you to create a Linq statement
that returns per Person a new object that contains Age, IsMarried,
whether it is an adult and to make it difficult: one Property called
Name which is a combination of First and Last
The function SelectData would be something like this:
IEnumerable<TResult> SelectData<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
return source.Select(selector);
}
Usage:
problem 1: return per Person a new object that contains the
properties First and Last.
var result = Persons.SelectData(person => new
{
First = person.First,
Last = person.Last,
});
problem 2: return per Person a new object that contains Age, IsMarried, whether he is an adult and one Property called Name which is a combination
of First and Last
var result = Persons.SelectData(person => new
{
Age = person.Name,
IsMarried = person.IsMarried,
IsAdult = person.Age > 21,
Name = new
{
First = person.First,
Last = person.Last,
},
});
Well let's face it, your SelectData is nothing more than Enumerable.Select
You could of course create a function where you'd let the caller provide a list of properties he wants, but (1) that would limit his possibilities to design the end result and (2) it would be way more typing for him to call the function.
Instead of:
.Select(p => new
{
P1 = p.Property1,
P2 = p.Property2,
}
he would have to type something like
.SelectData(new List<Func<TSource, TResult>()
{
p => p.Property1, // first element of the property list
p -> p.Property2, // second element of the property list
}
You won't be able to name the returned properties, you won't be able to combine several properties into one:
.Select(p => p.First + p.Last)
And what would you gain by it?
Highly discouraged requirement!
You could achive similar result using Reflection and Extension Method
Model:
namespace ConsoleApplication2
{
class Person
{
public string First { get; set; }
public string Last { get; set; }
public bool IsMarried { get; set; }
public int Age { get; set; }
}
}
Service:
using System.Collections.Generic;
using System.Linq;
namespace Test
{
public static class Service
{
public static IQueryable<IQueryable<KeyValuePair<string, object>>> SelectData<T>(this IQueryable<T> queryable, string[] properties)
{
var queryResult = new List<IQueryable<KeyValuePair<string, object>>>();
foreach (T entity in queryable)
{
var entityProperties = new List<KeyValuePair<string, object>>();
foreach (string property in properties)
{
var value = typeof(T).GetProperty(property).GetValue(entity);
var entityProperty = new KeyValuePair<string, object>(property, value);
entityProperties.Add(entityProperty);
}
queryResult.Add(entityProperties.AsQueryable());
}
return queryResult.AsQueryable();
}
}
}
Usage:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var list = new List<Person>()
{
new Person()
{
Age = 18,
First = "test1",
IsMarried = false,
Last = "test2"
},
new Person()
{
Age = 40,
First = "test3",
IsMarried = true,
Last = "test4"
}
};
var queryableList = list.AsQueryable();
string[] properties = { "Age", "Last" };
var result = queryableList.SelectData(properties);
foreach (var element in result)
{
foreach (var property in element)
{
Console.WriteLine($"{property.Key}: {property.Value}");
}
}
Console.ReadKey();
}
}
}
Result:
Age: 18
Last: test2
Age: 40
Last: test4

List Distinct is not working in LINQ instead of GroupBy

Thanks in advance. I can get required output when using var but i want to get required output by using Distinct in List<>.
InventoryDetails.cs
public class InventoryDetails
{
public int? PersonalInventoryGroupId { get; set; }
public int? PersonalInventoryBinId { get; set; }
}
InventoryController.cs
[HttpGet("GetInventory")]
public IActionResult GetInventory(int id)
{
//Below code will return distinct record
var inventory = (from i in _context.TempTbl
where i.TempId == id
select new
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).ToList().Distinct().ToList();
//Below code is not doing distinct
List<InventoryDetails> inventory = (from i in _context.TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).ToList().Distinct().ToList();
}
If i use var as return type, then i am able to get distinct records. Could some one assist it.
Please try like this it may help.
IList<InventoryDetails> inventory = _context.InventoryDetails.Where(x=>x.TempId == id).GroupBy(p => new {p.PersonalInventoryGroupId, p.PersonalInventoryBinId } )
.Select(g => g.First())
.ToList();
You need to override Equals and GetHashCode.
First, let's see the AnonymousType vs InventoryDetails
var AnonymousTypeObj1 = new { PersonalInventoryGroupId = 1, PersonalInventoryBinId = 1 };
var AnonymousTypeObj2 = new { PersonalInventoryGroupId = 1, PersonalInventoryBinId = 1 };
Console.WriteLine(AnonymousTypeObj1.Equals(AnonymousTypeObj2)); // True
var InventoryDetailsObj1 = new InventoryDetails { PersonalInventoryBinId = 1, PersonalInventoryGroupId = 1 };
var InvertoryDetailsObj2 = new InventoryDetails { PersonalInventoryBinId = 1, PersonalInventoryGroupId = 1 };
Console.WriteLine(InventoryDetailsObj1.Equals(InvertoryDetailsObj2)); // False
You can see the Equals behave differently which make Distinct behave differently. The problem is not var you mentioned in your question but AnonoymizeType
To make Distinct works as you expect, you need to override Equals and GetHashCode
public class InventoryDetails
{
public int? PersonalInventoryGroupId { get; set; }
public int? PersonalInventoryBinId { get; set; }
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj is InventoryDetails)
{
if (PersonalInventoryGroupId == (obj as InventoryDetails).PersonalInventoryGroupId
&& PersonalInventoryBinId == (obj as InventoryDetails).PersonalInventoryBinId)
return true;
}
return false;
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 23 + PersonalInventoryBinId.GetHashCode();
hash = hash * 23 + PersonalInventoryGroupId.GetHashCode();
return hash;
}
}
Another approach would be
List<InventoryDetails> inventory = (from i in TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).AsQueryable().ToList().Distinct(new customComparer()).ToList();
public class customComparer:IEqualityComparer<InventoryDetails>
{
public bool Equals(InventoryDetails x, InventoryDetails y)
{
if (x.TempId == y.TempId && x.PersonalInventoryBinId == y.PersonalInventoryBinId
&& x.PersonalInventoryGroupId == y.PersonalInventoryGroupId)
{
return true;
}
return false;
}
public int GetHashCode(InventoryDetails obj)
{
return string.Concat(obj.PersonalInventoryBinId.ToString(),
obj.PersonalInventoryGroupId.ToString(),
obj.TempId.ToString()).GetHashCode();
}
}
As said in a comment by Ivan, you make your life difficult by calling ToList before Distinct. This prevents the SQL provider from incorporating the Distinct call into the generated SQL statement. But that leaves the question: what causes the difference?
The first query generates anonymous type instances. As per the C# specification, by default anonymous types (in C#) are equal when their properties and property values are equal (structural equality). Conversely, by default, reference types (like InventoryDetails) are equal when their reference (say memory address) is equal (reference equality or identity). They can be made equal by overriding their Equals and GetHashcode methods, as some people suggested to do.
But that's not necessary if you remove the first ToList():
var inventory = (from i in _context.TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).Distinct().ToList();
Now the whole statement until ToList() is an IQueryable that can be translated into SQL. The SQL is executed and the database returns a distinct result set of raw records from which EF materializes InventoryDetails objects. The C# runtime code was even never aware of duplicates!

LINQ Query to join three tables

I need a help in LINQ Query for the below.
public interface IBrand
{
int BrandId { get; set; }
IEnumerable<IBuyingAgency> BuyingAgencies { get; set; }
}
public interface IBuyingAgency
{
int BuyingAgencyId { get; set; }
}
public interface IClientGroup
{
IBuyingAgency BuyingAgency { get; set; }
int ClientGroupId { get; set; }
}
1). var brands = LoggedInUserHelper.GetUser().GetBrands(roles); // returns IEnumerable<Tuple<IBrand, string>>
2). var buyingAgencies = LoggedInUserHelper.GetUser().GetBuyingAgencies(roles); //IEnumerable<IBuyingAgency>
3). var clientGroups = LoggedInUserHelper.GetUser().GetClientGroups(roles); //IEnumerable<IClientGroup>
function IEnumerable<IClientGroup> GetClientGroups( List<int> BrandIds)
{
var brands = LoggedInUserHelper.GetUser().GetBrands(roles); // returns IEnumerable<Tuple<IBrand, string>>
var buyingAgencies = LoggedInUserHelper.GetUser().GetBuyingAgencies(roles); //IEnumerable<IBuyingAgency>
var clientGroups = LoggedInUserHelper.GetUser().GetClientGroups(roles); //IEnumerable<IClientGroup>
var lstBrandagencies = brands.Where(brand => BrandIds.Contains(brand.Item1.BrandId) && brand.Item1.BuyingAgencies.Any( ba => buyingAgencies.Contains(ba.BuyingAgencyId))).SelectMany(brand => brand.Item1.BuyingAgencies);
var buyingAgencyIDs = lstBrandagencies.Select(b => b.BuyingAgencyId);
clientGroups = clientGroups.Where(cg => buyingAgencyIDs.Contains(cg.BuyingAgency.BuyingAgencyId));
return Mapper.Map<IEnumerable<IClientGroup>>(clientGroups.ToList());
}
I wrote the above function but not working, it gets all the clientgroups instead of filtering
I wants to write a query to get all ClientGroups whch satisfies the below condition
1. retrieve the brand from brands ( above ) that matches the list of brandId's passing in as parameter
2. Than get all the buyingAgencies under brands (1) above which matches with the id's of (2) above
3. Finally get all clientgroups which matches with the buyingAgency retrieving in step (2)
Please can you help.
you are not filtering from your source 2) in this line
var buyingAgencyIDs = lstBrandagencies.Select(b => b.BuyingAgencyId);
just projecting from the previous query.
If I understood correctly you want to do this.
var lstBrandagencies = (from a in brands
where BrandIds.Contains(a.Item1.BrandId )
select a).SelectMany (b => b.Item1.BuyingAgencies )
.Select (b => b.BuyingAgencyId );
var buyingAgencyIDs = from a in buyingAgencies
where lstBrandagencies.Contains(a.BuyingAgencyId )
select a.BuyingAgencyId;
var clientGroupsResult = clientGroups.Where(cg => buyingAgencyIDs.Contains(cg.BuyingAgency.BuyingAgencyId));

Linq to Sql Using a function to set a value

I wanted to get from a database a IEnumerable<T> and within the 'Select' method using a function to return a string value. But I always get back the
'method cannot be translated into a store expression'
error.
I already took a look all the post on Stack Overflow about the error 'LINQ to Entities does not recognize the method .... and this method cannot be translated into a store expression"
The only way that I found to get around this error is apply the function after the query has run.
void Main()
{
int eventId = 17;
IEnumerable<OccurrenceDropDownList> model = Occurrences.Select (s => new OccurrenceDropDownList
{
OccurrenceId = s.OccurrenceId,
Name = s.Name
})
.AsEnumerable()
.Select(m => new OccurrenceDropDownList
{
OccurrenceId = m.OccurrenceId,
Name = m.Name,
Selected = setSelected(m.OccurrenceId, eventId)
}).AsEnumerable();
foreach(var item in model)
{
Console.WriteLine(item.Name + " - id : " + item.OccurrenceId + " " + item.Selected);
}
}
public class OccurrenceDropDownList
{
public int OccurrenceId { get; set; }
public string Name { get; set; }
public string Selected { get; set; }
}
static string setSelected(int occurrence, int selectedid){
if(occurrence == selectedid){
return "selected";
}
return "";
}
Is there any way to apply the function as result of the first query?
It should be simplier:
int eventId = 17;
IEnumerable<OccurrenceDropDownList> model = Occurrences
.Select(s => new OccurrenceDropDownList
{
OccurrenceId = s.OccurrenceId,
Name = s.Name,
//magic ternary if
Selected = (eventId == s.OccurrenceId) ? "selected" : String.Empty
});
That's all. I used ternary if operator that should be translated to SQL.

Fail to iterate through collection returned

I have following program that fetches the data from DB and sends it to Main. I am able to iterate through the result in the function but not in Main.
Program is below :
void Main()
{
var data = GetAllCountry();
// foreach( var t in data)
// {
// Console.WriteLine("{0}", t.country.ID); //fails here; says country not found
// }
}
// Define other methods and classes here
public IEnumerable GetAllCountry()
{
var countries = COUNTRY.Select(c => new
{
country = new
{
ID = c.ID,
Description = c.DESCRIPTION,
CountryPhoneCode = c.COUNTRY_PHONE_CODE,
Currency = c.CURRENCY.CURRENCY_SYMBOL,
}
});
foreach( var t in countries)
{
Console.WriteLine("{0}", t.country.ID);//works here and I am able to access t.country.ID here...
}
return countries;
}
What wrong with this ? what are required modifications ?
I believe as you are returning IEnumerable rather than IEnumerable<T>, it is not able to get the object type.
If you create a class for Country and the method returns IEnumerable<Country> it would work
public IEnumerable<Country> GetAllCountry()
{
var countries = COUNTRY.Select(c => new
{
country = new Country
{
ID = c.ID,
Description = c.DESCRIPTION,
CountryPhoneCode = c.COUNTRY_PHONE_CODE,
Currency = c.CURRENCY.CURRENCY_SYMBOL,
}
});
foreach( var t in countries)
{
Console.WriteLine("{0}", t.country.ID);//works here and I am able to access t.country.ID here...
}
return countries;
}

Resources