IQueryable C# Select - c#

this is my code... but i need select only column to display in my Datagridview.
I Need the code to select only some columns.. example
Select{t => t.usu_Login, t => t.usu_Login}
public List<tb_usuario> Get(FilterDefinition filter)
{
var contexto = new indNET_Entities();
IQueryable<tb_usuario> Consulta = contexto.tb_usuario.AsQueryable<tb_usuario>()
.Where(t => t.usu_Ativo == 1)
.OrderBy(t => t.usu_Login);
return Consulta.ToList();
}

If you only want a limited number of columns and you intend to pass the result out of the method, first declare a concrete type to describe the elements.
public class UsuarioData
{
public string UsuLogin { get; set; } // or whatever
public string UsuName { get; set; } // or whatever
}
Then you can use this in the return type for the method
public List<UsuarioData> Get(...)
And finally, use the type in your select.
var consulta = contexto.tb_usuario.Where(whatever).OrderBy(whatever)
.Select(t => new UsuarioData
{
UsuLogin = t.usu_login,
UsuName = t.usu_name
}
);
return consulta.ToList();
And, of course, your callers should expect to get this as the result (or just use type inference with var).

IQueryable<tb_usuario> Consulta = contexto.tb_usuario.AsQueryable<tb_usuario>()
.Where(t => t.usu_Ativo == 1)
.OrderBy(t => t.usu_Login)
.Select(t => t.ColumnName);

Well there is a few ways you could do this, the easiest way:
grdvwHoldings.DataSource = Model.Holdings
.Select(x=> new
{ Name= x.HoldingName,
CustomerName = x.FundCustomerName
}).ToList();
grdvwHoldings.DataBind();
Alternatively you could create a class and substitute the new {} for the class and do it at the data layer level.

Try this:
(contexto.AsEnumerable()
select new {usu_Login=r.Field<string>("usu_Login")}).ToList();

Related

Order by multiple lists of object

I've three lists in an object and want to perform order by operation using LINQ
object containing lists
public class ApplicationCommunications
{
public ApplicationCommunications()
{
listNotification = new List<ApplicationNotifications>();
listEmail = new List<ApplicationEmail>();
listSMS = new List<ApplicationSMS>();
}
public List<ApplicationNotifications> listNotification { get; set; }
public List<ApplicationEmail> listEmail { get; set; }
public List<ApplicationSMS> listSMS { get; set; }
}
Getting data from db
ApplicationCommunications applicationCommunications = new ApplicationCommunications();
applicationCommunications.listNotification = GetApplicationNotification(applicationId).Select(c => new ApplicationNotifications
{
NotificationId = c.NotificationId,
Message = c.Message,
SendDate = c.SendDate.Value
}).ToList();
applicationCommunications.listEmail = GetApplicationEmails(applicationId).Select(t => new ApplicationEmail
{
EmailContent = t.Body,
EmailAddress = t.Email,
SendDate = t.SendDate.Value,
}).ToList();
applicationCommunications.listSMS = GetApplicationMessage(applicationId).Select(t => new ApplicationSMS
{
SMSContent = t.Body,
PhoneNumber = t.Phone,
SendDate = t.SendDate.Value,
}).ToList();
We've three lists each list of the object has "senddate" property now I want to make a new list from these three lists where we will have data in order. Is that possible?
How we can perform order by with send date? simply I want to display data in order.
Select method gives you Enumerable type of list. Enumerable can be ordered by OrderBy, so simply do this
applicationCommunications.listNotification = GetApplicationNotification(applicationId).Select(c => new ApplicationNotifications
{
NotificationId = c.NotificationId,
Message = c.Message,
NotificationSendDate = c.SendDate.Value
})
.OrderBy(an => an.NotificationSendDate)
.ThenBy(an => an.NotificationId)
.ToList();
EDIT:
You can read more here https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=net-5.0
pardon for the incomplete question. We've three lists each list of the
object has "senddate" property now I want to make a new list from
these three lists where we will have data in order. Is that possible?
As shown in the other answer you need OrderBy:
List<DateTime> orderedSendDates = applicationCommunications.listNotification
.Select(x => x.NotificationSendDate)
.Concat(applicationCommunications.listEmail.Select(x => x.EmailSendDate))
.Concat(applicationCommunications.listSMS.Select(x => x.SMSSendDate))
.OrderBy(dt => dt)
.ToList();
If you want unique DateTimes use Distinct before the OrderBy.
If you don't have these properties initialized when you want the list you could do:
List<DateTime> orderedSendDates =
GetApplicationNotification(applicationId).Select(x => x.SendDate)
.Concat(GetApplicationEmails(applicationId).Select(x => x.SendDate))
.Concat(GetApplicationMessage(applicationId).Select(x => x.SendDate))
.Where(sendDateOrNull => sendDateOrNull.HasValue)
.Select(sendDateOrNull => sendDateOrNull.Value)
.OrderBy(dt => dt)
.ToList();
If you want a big list containing the different types of elements, ordered by sendDate (but not just a list of dateTime), you may first create a common type for that :
public class SentElement {
public string ElementDescription {get ; set;}
public DateTime SendDate { get; set;}
}
Then map your different types to the common type using Select, filling the description the way you want for each type of element:
var listNotification = GetApplicationNotification(applicationId).Select(c => new SentElement
{
ElementDescription = c.NotificationId + c.Message,
SendDate= c.SendDate.Value
}).ToList();
var listEmail = GetApplicationEmails(applicationId).Select(t => new SentElement
{
ElementDescription = t.EmailContent + t.EmailAddress,
SendDate = t.SendDate.Value,
}).ToList();
var listSMS = GetApplicationMessage(applicationId).Select(t => new SentElement
{
ElementDescription = t.Body + t.Phone,
SendDate = t.SendDate.Value,
}).ToList();
And finally merging and ordering the result :
var mergedList = listNotification.Concat(listEmail).Concat(listSMS).OrderByDescending(t=> t.SendDate);

Best way to find values not in two lists c#

I have two lists which I need to compare (carOptions and custOptions).
Both of these lists are in my Customer class like below:
public class CustomerDTO
{
public int CustomerId { get; set; }
//other props removed for brevity
public List<OptionDTO> SelectedCarOptions { get; set; }
public List<OptionDTO> SelectedCustomerOptions { get; set; }
}
var existingData = _myRepository.GetDataByCustomer(customerId, year);
var existingCarOptions = existingData.Select(f => f.SelectedCarOptions);
var existingCustomerOptions = existingData.Select(f => f.SelectedCustomerOptions);
existingData is an IEnumerable of CustomerDTO and then existingCarOptions and existingCustomerOptions is an IEnumerable<List<OptionDTO>>
In the method, I have a list of IEnumerable<OptionDTO> options that gets passed in. I then break this down into car or customer based on the Enum as below:
var newCarOptions = options.Where(o => o.OptionTypeID == OptionType.CarOptions);
var newCustomerOptions = options.Where(o => o.OptionTypeID == OptionType.CustomerOptions).ToList();
What I need to do is find which options are in one collection but no in the other.
I tried as below but getting an Error on the Except (I maybe need to create my own static method in that class) but I am not sure this is the best approach really?
if (existingCarOptions.Count() != newCarOptions.Count())
{
//var test = newCarOptions.Except(existingCarOptions);
}
if (existingCustomerOptions.Count() != newCustomerOptions.Count())
{
//var test2 = newCustomerOptions.Except(existingCustomerOptions);
}
Is it also quite a bit of code in the method - I could split it out into sperate methods if required but perhaps there is a simpler way I could achieve this?
I'm assuming OptionDTO has a property called Id, which uniquely identifies an option (you have to change the code accordingly if this is not the case), you may use HashSets to quickly find unmatched OptionsDTOs, while keeping the overall time cost O(n) (where n is the max number of combined options).
Create the existing options sets:
var existingCarOptions = existingData.SelectMany(d => d.SelectedCarOptions).Select(o => o.Id);
var existingCustomerOptions = existingData.SelectMany(d => d.SelectedCustomerOptions).Select(o => o.Id);
var existingCarOptionsIds = new HashSet<int>(existingCarOptions);
var existingCustomerOptionsIds = new HashSet<int>(existingCustomerOptions );
Then you extract options missing in existing sets with:
var unmatchedCarOptions = newCarOptions.Where(o => !existingCarOptionsIds.Contains(o.Id));
var unmatchedCustomerOptions = newCustomerOptions.Where(o => !existingCustomerOptionsIds.Contains(o.Id));
If you want to compare two classes you can use IEqualityComparer
public class OptionComparer : IEqualityComparer<OptionDTO>
{
public bool Equals(OptionDTO x, OptionDTO y)
{
if (object.ReferenceEquals(x, y))
{
return true;
}
if (object.ReferenceEquals(x, null) ||
object.ReferenceEquals(y, null))
{
return false;
}
return x.OptionTypeID == y.OptionTypeID ;
}
public int GetHashCode(OptionDTO obj)
{
if (obj == null)
{
return 0;
}
return obj.OptionTypeID.GetHashCode();
}
With using this you can ıdentify that What is the concept of equality for these classes.
Now we can find different values..
public List<OptionDTO>CalculateDiffBetweenLists(List<OptionDTO> left, List<OptionDTO> right){
List<OptionDTO> optionDiff;
optionDiff = left.Except(right, new OptionComparer ()).ToList();
return optionDiff ;
}

get collection with where clause as collection in Linq

Here is my service method:
public List<RelatedInvoiceData> GetRelatedInvoices(InvoiceSearch invoiceSearchFilters)
{
List<InvoiceInfoView> invoices = _wiseStepDbContext.InvoiceInfoView.Where(i => i.RecruiterCompanyId == _securityManager.CurrentRecruiterCompanyId).ToList();
List<RelatedInvoiceData> relatedInvoiceViewCollection = GetRelatedInvoiceCollection(invoices);
if (invoiceSearchFilters.CustomerId > 0)
{
relatedInvoiceViewCollection = relatedInvoiceViewCollection.Where(i => i.CustomerId == invoiceSearchFilters.CustomerId).ToList();
}
if (invoiceSearchFilters.VendorId > 0)
{
relatedInvoiceViewCollection = relatedInvoiceViewCollection.Where(i => i.VendorId == invoiceSearchFilters.VendorId).ToList();
}
return relatedInvoiceViewCollection;
}
here is my filterObject :
public class InvoiceSearch
{
public int[] CustomerId { get; set; }
public int[] VendorId { get; set; }
}
Previously I used where in linq for single customer Id now i want filter with multiple customerIds and multiple VendorIds.
Now I want to go with array of CustomerIds. How to write LINQ for Array in Where clause. Thanks for any help
If I understand correctly, you mean that i.CustomerId is now an array or List<>. If that's the case, then you can use the.Contains() method. Something like this should do what you want: relatedInvoiceViewCollection = relatedInvoiceViewCollection.Where(i => i.CustomerId.Contains(invoiceSearchFilters.CustomerId)).ToList();
Edit: This question may be helpful if you want to check for intersections in two arrays, which you can do in your case like this:relatedInvoiceViewCollection = relatedInvoiceViewCollection.Where(i => i.CustomerId.Intersect(invoiceSearchFilters.CustomerId).Any()).ToList();
relatedInvoiceViewCollection.Where(x => relatedInvoiceViewCollection.Contains(invoiceSearchFilters.CustomerId)).ToList();
or
relatedInvoiceViewCollection.Where(x => x.Contains(invoiceSearchFilters.CustomerId)).ToList();

c# Searching List<t> inside another List<T>

How would I search for a value within a List<t> inside another List<t>
i.e.
//FooInner Class
public class FooInner {
public int FooInnerId { get; set; }
public String FooValue { get; set; }
}
//FooOuter Class
public class FooOuter {
public int FooOuterId { get; set; }
public List<FooInner> FooInnerCollection { get; set; }
}
If I just wanted to find a value in the outer class
// Working code
List<FooOuter> fooOuterCollection = GetSomeData();
var tmp = fooOuterCollection.Find( f => f.FooOuterId == 2 );
But what if I wanted the FooInner Object where FooOuterId == 2 and FooInnerCollection.FooInnerId == 4 (or contains depending how you look at it).
Hopefully that makes sense.
fooOuterCollection
.Where(outer => outer.FooOuterID == 2)
.SelectMany(outer => outer.FooInnerCollection)
.FirstOrDefault(fooInner => fooInner.FooInnerId == 4);
First we filter the outer objects to only include those with Id == 2
Then we use SelectMany to flatten out the multiple InnerCollections that we may find
Finally we filter based on the inner Id == 4
You can get inner object like this-
var temp= fooOuterCollection.Where(f => f.FooOuterId == 2)
.SelectMany(f => f.FooInnerCollection)
.FirstOrDefault(fi => fi.FooInnerId == 4));
If you need outer object, you need to use Any() extension method to see if inner list contains required element -
var temp = fooOuterCollection.FirstOrDefault(f => f.FooOuterId == 2 &&
f.FooInnerCollection.Any(fi => fi.FooInnerId == 4);
You could just use LINQ's query syntax:
var results = from o in outerList
where o.FooOuterId == 2
from i in o.FooInnerCollection
where i.FooInnerId == 4
select i;

How to configure AutoFixture to use an enum value as seed when creating many of a certain type?

I have the following types:
public enum Status
{
Online,
Offline
}
public class User
{
private readonly Status _status;
public User(Status status) { _status = status; }
public Status Status {get {return _status; }}
public string Name {get;set;}
}
Now, when executing fixture.CreateMany<User> I want AutoFixture to return two Users, one per status. All other properties - like Name - should be filled with anonymous data.
Question:
How to configure AutoFixture to do this?
I tried the following this:
Register collection that news up the User object:
fixture.Register(
() => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s =>
new User(s)));
The problem with this approach is that AutoFixture doesn't fill the other properties like Name
Customize User to use a factory and register a collection that uses fixture.Create:
f.Customize<User>(c => c.FromFactory((Status s) => new User(s)));
f.Register(() =>
Enum.GetValues(typeof(Status))
.Cast<Status>()
.Select(s => (User)f.Create(new SeededRequest(typeof(User), s),
new SpecimenContext(f))));
That didn't work either. The seed isn't being used.
You could do this:
var users = new Fixture().Create<Generator<User>>();
var onlineUser = users.Where(u => u.Status == Status.Online).First();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
If you're using AutoFixture.Xunit, the declarative equivalent is:
[Theory, AutoData]
public void CreateOneOfEachDeclaratively(Generator<User> users)
{
var onlineUser = users.Where(u => u.Status == Status.Online).First();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
// Use onlineUser and offlineUser here...
}
You may declare and use a customization, e.g. StatusGenerator:
var fixture = new Fixture();
fixture.RepeatCount = 2;
fixture.Customizations.Add(new StatusGenerator());
var result = fixture.CreateMany<User>();
A hypothetical implementation of the StatusGenerator could be the following:
internal class StatusGenerator : ISpecimenBuilder
{
private readonly Status[] values;
private int i;
internal StatusGenerator()
{
this.values =
Enum.GetValues(typeof(Status)).Cast<Status>().ToArray();
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi == null || !pi.ParameterType.IsEnum)
return new NoSpecimen(request);
return this.values[i == this.values.Length - 1 ? i = 0 : ++i];
}
}
Based on Mark's answer, this is what I am using now:
fixture.Customize<User>(c => c.Without(x => x.Status));
fixture.Customize<IEnumerable<User>>(
c =>
c.FromFactory(
() => Enum.GetValues(typeof(Status)).Cast<Status>()
.Select(s => users.First(u => u.Status == s))));
fixture.Create<IEnumerable<User>>(); // returns two Users
I know it is already answered and the Generator was a very interesting finding.
I think there is a much simpler approach for this problem.
var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length;
var users = fixture.CreateMany<User>(numberOfEnumValues);
In case the constructor is more complicated, with multiple Status values, or the model has property setters of Status type. Then you generally have a problem, and the generator might blow as well.
Say that:
public class SuperUser : User
{
public SuperUser(Status status, Status shownStatus): base(status)
{
}
}
Then this will never be evaluated:
var users = fixture.Create<Generator<SuperUser>>();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
Current way of doing this with AutoFixture 4.17.0
fixture
.Build<User>
.With(u => u.Status, Status.Offline)
.CreateMany(5)
.ToList();

Categories

Resources