How do you do alias in Select method (LINQ) - c#

I'm trying to alias the string list with a named column:
var providers = EMRRepository.GetProviders().Select(x => x as name);
where 'GetProviders()' returns a List<string>

It's called a "Projection", just select a new anonymous type.
var projection = data.Select( x => new { FieldName = x.Property } );

You are looking to select into a new anonymous type.
var providers = EMRRepository.GetProviders().Select(x => new { Name = x });

Related

how to use an expression in a select clause

consider the following pseudp code
Expression<Func<E,Datetime?>> expr =
e => (e.d1 ?? e.Rel.d1) ?? e.d2;
var q = myContext.E_DbSet.Select(x => new someDeclaredType {
Id = x.Id,
V = expr
});
=> CS0029 Cannot implicitly convert type 'System.Linq.Expressions.Expression>' to 'System.DateTime?'
if I try with compile
Expression<Func<E,Datetime?>> expr =
(e => (e.d1 ?? e.Rel.d1) ?? e.d2).Compile();
var q = myContext.E_DbSet.Select(x => new someDeclaredType {
Id = x.Id,
V = expr(x)
});
=> NotSupportedException: node type 'Invoke' of LINQ expression is not suported in LINQ to Entities.
I read Invoke an Expression in a Select statement - LINQ to Entity Framework. But this is not my exact case. I need to include an existing expression into my select clause. This expression comes as the result of a function call. So I must use expr in my select clause.
How can it be done ?
Maybe something like this:
Expression<Func<E,someDeclaredType>> expr =
e => new someDeclaredType()
{
Id = e.Id,
V = (e.d1 ?? e.Rel.d1) ?? e.d2
};
var q = myContext.E_DbSet.Select(expr);
I finally found a way:
Expression<Func<E,Datetime?>> expr =
e => (e.d1 ?? e.Rel.d1) ?? e.d2;
Expression<Func<E,someDeclaredType>> sel =
x => new someDeclaredType {
Id = x.Id,
V = expr.Compile()(x)
};
var q = myContext.E_DbSet.Select(sel.Compile());
another coding is (from #Anthony):
Expression<Func<E, someDeclaredType>> sel =
e => new someDeclaredType()
{
Id = e.Id,
V = expr.Compile()(e)
};
q = Files.Select(sel.Compile());
by the sample: dotnetfiddle
Please not that the code is designed for linq to entities. It may fire exception in linq to object due to Rel = null.

How to select items using lambda expression

I am selecting data from a data store
I am able to fetch first array [0] {IHSWCFService.ServiceReference1.Observation} using below query
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
PeriodData = Convert.ToDateTime(a.ObservationVector.Select(x => x.Period).FirstOrDefault()),
StatusID = Convert.ToInt32(a.ObservationVector.Select(x => x.StatusId).ToList()),
Price = Convert.ToDouble(a.ObservationVector.Select(x => x.price).FirstOrDefault()),
});
But I want to select next array also. as showing in below screen screenshot
[0]{IHSWCFService.ServiceReference1.Observation}
[1]{IHSWCFService.ServiceReference1.Observation}
[2]{IHSWCFService.ServiceReference1.Observation}
Could you please help me. Thanks
You might want all your properties in IHSData to be lists:
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
PeriodData = a.ObservationVector.Select(x => Convert.ToDateTime(x.Period)).ToList(),
StatusID = a.ObservationVector.Select(x => Convert.ToInt32(x.StatusId)).ToList(),
Price = a.ObservationVector.Select(x => Convert.ToDouble(x.price)).ToList(),
});
Which is not such a good idea, because you have to index them separately. So another option would be to use SelectMany:
var newData = data
.SelectMany(a => a.ObservationVector.Select(v =>
new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId), // parent PriceId
PeriodData = Convert.ToDateTime(v.Period),
StatusID = Convert.ToInt32(v.StatusId),
Price = Convert.ToDouble(v.price),
}))
.ToList();
The latter approach will create a separate IHSData instance for each ObservationVector, and some of them will share the same PriceId of the parent class.
Or, the third approach would be to have a new class, which would be the "parsed version of the ObservationVector", i.e. contain properties for parsed values, something like:
var newData = data.Select(a => new IHSData
{
PriceSymbol = Convert.ToString(a.PriceId),
Data = a.ObservationVector.Select(x => ConvertObservationVector(x)).ToList()
});
where ConvertObservationVector is a method which converts from an ObservationVector to your parsed class.

Select Statements in LINQ Efficiency

For code shown below, I'm wondering is there a more efficient way of assigning the Status and Types in the select statement? There is no relationship between the contract and the statuses/types as the contract items are coming from an API call and the statuses/types are from a local database.
The part in question is
Status = statuses.FirstOrDefault(y => y.StatusId == x.StatusId)
Type = types.FirstOrDefault(y => y.TypeId == x.TypeId)
Is there a better way of assigning these?
var statuses = this.StatusRepository.GetActiveStatuses().ToList();
var types = this.TypeRepository.GetActiveTypes().ToList();
var contracts = this.ContractApi.GetCurrentContracts().Select(x => new ContractItem {
Id = x.Id,
Name = x.Name,
Status = statuses.FirstOrDefault(y => y.StatusId == x.StatusId) ?? Status.Empty(),
Type = types.FirstOrDefault(y => y.TypeId == x.TypeId) ?? Type.Empty()
});
For better performance you should use a dictionary or lookup:
var statuses = this.StatusRepository.GetActiveStatuses().ToLookup(x => x.StatusId);
var types = this.TypeRepository.GetActiveTypes().ToLookup(x => x.TypeId);
var emptyStatus = Status.Empty();
var emptyType = Type.Empty();
var contracts = this.ContractApi.GetCurrentContracts()
.Select(x => new ContractItem {
Id = x.Id,
Name = x.Name,
Status = statuses[x.StatusId].DefaultIfEmpty(emptyStatus).First(),
Type = types[x.TypeId].DefaultIfEmpty(emptyType).First()
});
The lookup is more readable because it enables to use DefaultIfEmpty
If you know they will exist in your local database you could store them in a Dictionary like;
var statusDict = this.StatusRepository.GetActiveStatuses().ToDictionary(s => s.StatusId);
....
Status = statusDict[x.StatusId]

How to change in elegant way List<> structure

I am using LINQ to entitiy in my project.
I have this LINQ:
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
select new
{
Id = inspArch.Id,
clientId = inspArch.CustomerId,
authId = inspAuth.Id
}).ToList();
After LINQ is executed result has this value :
Is there any elegant way (for example using LINQ or change above existing LINQ) to create from the list above, new list like that:
I haven't built this to see if it compiles, but this should work. You need to aggregate the Id and AuthId fields.
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
select new
{
Id = inspArch.Id,
clientId = inspArch.CustomerId,
authId = inspAuth.Id
})
.GroupBy(g => g.clientId)
.select(s => new {
Id = string.Join(",", s.Select(ss => ss.Id.ToString())),
ClientId = s.Key,
AuthId = string.Join(",", s.Select(ss => ss.authId.ToString()).Distinct()),
}).ToList();
You need group by and you can apply String.Join on the resulting IGrouping:-
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
group new { inspArch, inspAuth } by inspArch.CustomerId into g
select new
{
Id = String.Join(",",g.Select(x => x.inspArch.Id),
clientId = x.Key,
authId = String.Join(",",g.Select(x => x.inspAuth.Id)
}).ToList();
The tricky part here is to group both objects i.e. new { inspArch, inspAuth } because we need to access properties from both.
Update:
Since this is entity framework, it won't be able to translate the method String.Join to SQL, so we can bring back the grouped object to memory using AsEnumerable and then project it like this:-
var result = (from inspArch in inspectionArchives
from inspAuth in inspArch.InspectionAuthority
group new { inspArch, inspAuth } by inspArch.CustomerId into g
select g).AsEnumerable()
.Select(g => new
{
Id = String.Join(",",g.Select(x => x.inspArch.Id),
clientId = x.Key,
authId = String.Join(",",g.Select(x => x.inspAuth.Id)
}).ToList();

Concat strings in a projection (Linq)

How can I concat two string in a projection?
This is what I have so far:
IEnumerable<NameIdentity> data = null;
JsonResult res;
using (DBContext _db = new DBContext())
{
data = MyEntity.GetEntities(_db).OrderBy(a=> a.name)
.Select(b=> new NameIdentity
{
ID = b.entityID,
Name = String.Join(" - ", new String[]{ b.year, b.name })
});
res = Json(data.ToList(), JsonRequestBehavior.AllowGet);
}
I need to concatenate the year and name properties in the Name propety of my projection.
The error that is giving me is an "NotSupportedException" that says that the LINQ to Entities doesn't recognize de Join() method and it cannot be translated to a store expression.
data = MyEntity.GetEntities(_db).OrderBy(a=> a.name)
.Select(b=> new NameIdentity
{
ID = b.entityID,
Name = b.year +"-" + b.name
});
While you are using linq-to-entities you cannot use arbitrary .NET methods in query, You can use EdmFunctions, Here I have use EdmFunctions.Concat
data = MyEntity.GetEntities(_db).OrderBy(a=> a.name)
.Select(b=> new NameIdentity
{
ID = b.entityID,
Name = EdmFunctions.Concat(b.year, "-", b.name)
});
You can also use Canonical functions

Categories

Resources