I have a couple tables that are kind of unrelated - id like to search through both of them and create a type that i can sift through later
something like this doesnt work
var results = from dog in _dataContext.Dogs
where dog.Name.Contains(search)
from catin _dataContext.Cats
where cat.Name.Contains(search)
select new AnimalSearchResults
{
Dog = dog,
Cat = cat
};
return results;
I basically want to create a list of "AnimalSearchResults" that contains all dogs and all cats that have that name
Whats the best way to do something like this?
Sounds like you want to Union the two results so your basic query would be something like:
var results = (from dog in _dataContext.Dogs
where dog.Name.Contains(search))
.Union
(from cat in _dataContext.Cats
where cat.Name.Contains(search));
The other workaround would be to have the class Cat and the class Dog derivate the same base class, which would then carry the name.
Here's an example
public class Pet
{
public string Name {get; set;}
}
public class Dog : Pet {...}
public class Cat : Pet {...}
// I assume each classes have their singularity;
In your DataContext Object, create a GetPets() method, like this one :
public IEnumerable<Pet> GetPets()
{
return Cats.Cast().Union( Dogs.Cast() );
}
Then use LINQ on the Pets in the DataContext.
var results =
(from p in _dataContext.GetPets()
where p.Name.Contains(search)
select p);
This code would be more scalable, especially if u have more than 2 derivated classes.
{enjoy}
Related
I typically do mobile app development, which doesn't always have .Select. However, I've seen this used a bit, but I don't really know what it does or how it's doing whatever it does. It is anything like
from a in list select a // a.Property // new Thing { a.Property}
I'm asking because when I've seen code using .Select(), I was a bit confused by what it was doing.
.Select() is from method syntax for LINQ, select in your code from a in list select a is for query syntax. Both are same, query syntax compiles into method syntax.
You may see: Query Syntax and Method Syntax in LINQ (C#)
Projection:
Projection Operations - MSDN
Projection refers to the operation of transforming an object into a
new form that often consists only of those properties that will be
subsequently used. By using projection, you can construct a new type
that is built from each object. You can project a property and perform
a mathematical function on it. You can also project the original
object without changing it.
You may also see:
LINQ Projection
The process of transforming the results of a query is called
projection. You can project the results of a query after any filters
have been applied to change the type of the collection that is
returned.
Example from MSDN
List<string> words = new List<string>() { "an", "apple", "a", "day" };
var query = from word in words
select word.Substring(0, 1);
In the above example only first character from each string instance is selected / projected.
You can also select some fields from your collection and create an anonymous type or an instance of existing class, that process is called projection.
from a in list select new { ID = a.Id}
In the above code field Id is projected into an anonymous type ignoring other fields. Consider that your list has an object of type MyClass defined like:
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Now you can project the Id and Name to an anonymous type like:
Query Syntax:
var result = from a in list
select new
{
ID = a.Id,
Name = a.Name,
};
Method Syntax
var result = list.Select(r => new { ID = r.Id, Name = r.Name });
You can also project result to a new class. Consider you have a class like:
class TemporaryHolderClass
{
public int Id { get; set; }
public string Name { get; set; }
}
Then you can do:
Query Syntax:
var result = from a in list
select new TemporaryHolderClass
{
Id = a.Id,
Name = a.Name,
};
Method Syntax:
var result = list.Select(r => new TemporaryHolderClass
{
Id = r.Id,
Name = r.Name
});
You can also project to the same class, provided you are not trying to project to classes generated/created for LINQ to SQL or Entity Framework.
My summary is it takes results (or a subset of results) and allows you to quickly restructure it for use in the local context.
The select clause produces the results of the query and specifies the
"shape" or type of each returned element. For example, you can specify
whether your results will consist of complete Customer objects, just
one member, a subset of members, or some completely different result
type based on a computation or new object creation.
Source: http://msdn.microsoft.com/en-us/library/bb397927.aspx
There are a lot of possible uses for this but one is taking a complex object which of many other contains a property that is a string -- say Name -- and allows you to return an enumeration with just the entries of Name. I believe you can also do the opposite -- use that property ( for example) and create / return new type of object while passing in a property or properties.
It means "mapping". Map each element of a sequence to a transformed sequence. I hadn't comprehended its meaning before I looked at the image.
Where does the meaning of the word come from?
Simply, math! https://mathworld.wolfram.com/Projection.html
I have extracted some of my concrete classes into interfaces
I used to have a class called City, and it implements interface ICity
now i tried to do the following
public List<ICity> Cities { get; private set; }
var efCities = (from c in myentity.Cities
orderby c.CityName
select c);
Cities = (efCities.Select(o => new City() { Id = o.Id, Country = o.Country,
Province = o.Province, CityName = o.CityName }).ToList());
I get tuned the following:
Cannot implicitly convert type 'System.Collections.Generic.List<City>'
to 'System.Collections.Generic.List<ICity>'
as i understood it, since City implements ICity, i should be fine, no?
Isn't what I am doing in the same vein as going:
ICity c = new City();
No one has really said the reason why this doesn't work. Suppose Apple and Orange both implement IFruit:
List<Orange> oranges = new List<Orange>();
List<IFruit> fruits = oranges; // You are trying to do this, which is illegal.
// Suppose it were legal. Then you could do this:
fruits.Add(new Apple());
Because you can add an apple to a list of fruits, but that list is really a list of oranges! You just put an apple into a list of oranges, and apples are not oranges.
The C# compiler knows that this could happen, so it disallows it. Unfortunately, it does not disallow that for arrays:
Orange[] oranges = new Orange[1];
IFruit[] fruits = oranges; // dangerous, but legal!
fruits[0] = new Apple(); // legal at compile time, crashes at runtime.
This is a form of unsafe covariance. We decided to not allow the same dangerous pattern for interfaces; interfaces can only be covariant if the compiler can prove that such an error is impossible.
Unfortunately, generic type parameters do not follow the same typecasting rules as stand-alone types. They are restricted by what the generic type says it allows; this is called covariance and contravariance and, in C#, only arrays, interfaces and delegates can be covariant or contravariant. Concrete types like List cannot be (at least, as of C# 4.0).
(The reason generics don't work the way you think in general is because its impossible to know what the generic type does with its type parameters; covariance is intuitive because that's how simple assignments works, but in many cases what we really want is contravariance; since the compiler cannot make the decision for us, it defaults to neither unless you say otherwise.)
For more information on co/contravariance in C# 4 I'd recommend you check out Eric Lippert's series of posts about it, in particular:
http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx
and the MSDN article about it:
http://msdn.microsoft.com/en-us/library/dd799517.aspx
Fortunately, in this case there is a simple answer, the explicit IEnumerable.Cast method:
Cities = (efCities.Select(o => new City() { Id = o.Id, Country = o.Country,
Province = o.Province, CityName = o.CityName }).Cast<ICity>.ToList());
Another option is to use IEnumerable<T> instead of List<T>. IEnumerable<T> is covariant in T so your assignment would work:
interface IA
{
int Foo();
}
class A : IA
{
public int Foo()
{
return 0;
}
}
public DoStuff()
{
List<A> la = new List<A> { new A(), new A(), new A(), new A() };
// This is an error -- List<A> is not covariant with List<IA>
// List<IA> lia = la;
// This is fine; List<A> implements IEnumerable<A>
IEnumerable<A> iea = la;
// Also fine: IEnumerable<A> is covariant with IEnumerable<IA>
IEnumerable<IA> ieia = la;
}
It is not same as
ICity c = new City();
List<ICity> and List<City> are tehmselves types, and List<City> is not derived from List<ICity>.
Adding a cast to the selection would solve the problem:
Cities = (efCities.Select(o => (ICity)(new City() { Id = o.Id, Country = o.Country,
Province = o.Province, CityName = o.CityName })).ToList());
No. List<City> is not that same as List<ICity>. Instead of assigning the select.toList(); to cities try something like:
Cities.AddRange((efCities.Select(o => new City() { Id = o.Id, Country = o.Country, Province = o.Province, CityName = o.CityName }))
I have spent hours upon hours trying to figure out how to shape the data projected from linq to a strongly type view. My problem is I think my problem is I am unsure how to use IEnumberable and IGrouping.
Here is the linq:
var spec = from a in _entities.Approvals
join b in _entities.ApprovalSpecifications on a.HeaderlID equals b.HeaderlID into g
where a.ApprovalID == id
group a by a.HeaderlID into groupedByHeader
select new
{
Key = groupedByHeader.Key,
groupedByHeader
};
Can anyone suggest the method with which I should approach this? I am thinking a class for this would work best, but as I mentioned I'm not sure how to use IGrouping to build a class. Any help is appreciated!
Something like this?
class StronglyTypedGrouping {
public object Key { get; set; } // I can't infer Key type from the snippet.
public IEnumerable<Approval> Approvals { get; set; }
}
var spec = from a in _entities.Approvals
join b in _entities.ApprovalSpecifications on
a.HeaderlID equals b.HeaderlID into g
where a.ApprovalID == id
group a by a.HeaderlID into groupedByHeader
select new StronglyTypedGrouping {
Key = groupedByHeader.Key,
Approvals = groupedByHeader
};
Forgive me if this has been asked already. I've only just started using LINQ. I have the following Expression:
public static Expression<Func<TblCustomer, CustomerSummary>> SelectToSummary()
{
return m => (new CustomerSummary()
{
ID = m.ID,
CustomerName = m.CustomerName,
LastSalesContact = // This is a Person entity, no idea how to create it
});
}
I want to be able to populate LastSalesContact, which is a Person entity.
The details that I wish to populate come from m.LatestPerson, so how can I map over the fields from m.LatestPerson to LastSalesContact. I want the mapping to be re-useable, i.e. I do not want to do this:
LastSalesContact = new Person()
{
// Etc
}
Can I use a static Expression, such as this:
public static Expression<Func<TblUser, User>> SelectToUser()
{
return x => (new User()
{
// Populate
});
}
UPDATE:
This is what I need to do:
return m => (new CustomerSummary()
{
ID = m.ID,
CustomerName = m.CustomerName,
LastSalesContact = new Person()
{
PersonId = m.LatestPerson.PersonId,
PersonName = m.LatestPerson.PersonName,
Company = new Company()
{
CompanyId = m.LatestPerson.Company.CompanyId,
etc
}
}
});
But I will be re-using the Person() creation in about 10-15 different classes, so I don't want exactly the same code duplicated X amount of times. I'd probably also want to do the same for Company.
Can't you just use automapper for that?
public static Expression<Func<TblCustomer, CustomerSummary>> SelectToSummary()
{
return m => Mapper.Map<TblCustomer, CustommerSummary>(m);
}
You'd have to do some bootstrapping, but then it's very reusable.
UPDATE:
I may not be getting something, but what it the purpose of this function? If you just want to map one or collection of Tbl object to other objects, why have the expression?
You could just have something like this:
var customers = _customerRepository.GetAll(); // returns IEnumerable<TblCustomer>
var summaries = Mapper.Map<IEnumerable<TblCustomer>, IEnumerable<CustomerSummary>>(customers);
Or is there something I missed?
I don't think you'll be able to use a lambda expression to do this... you'll need to build up the expression tree by hand using the factory methods in Expression. It's unlikely to be pleasant, to be honest.
My generally preferred way of working out how to build up expression trees is to start with a simple example of what you want to do written as a lambda expression, and then decompile it. That should show you how the expression tree is built - although the C# compiler gets to use the metadata associated with properties more easily than we can (we have to use Type.GetProperty).
This is always assuming I've understood you correctly... it's quite possible that I haven't.
How about this:
public static Person CreatePerson(TblPerson data)
{
// ...
}
public static Expression<Func<TblPerson, Person>> CreatePersonExpression()
{
return d => CreatePerson(d);
}
return m => (new CustomerSummary()
{
ID = m.ID,
CustomerName = m.CustomerName,
LastSalesContact = CreatePerson(m.LatestPerson)
});
I'm just starting out with F# and I can't find the syntax to do object initialization like in C# 3.
I.e. given this:
public class Person {
public DateTime BirthDate { get; set; }
public string Name { get; set; }
}
how do I write the following in F#:
var p = new Person { Name = "John", BirthDate = DateTime.Now };
You can do it like this:
let p = new Person (Name = "John", BirthDate = DateTime.Now)
the answer from CMS is definitely correct. Here is just one addition that may be also helpful. In F#, you often want to write the type just using immutable properties. When using the "object initializer" syntax, the properties have to be mutable. An alternative in F# is to use named arguments, which gives you a similar syntax, but keeps things immutable:
type Person(name:string, ?birthDate) =
member x.Name = name
member x.BirthDate = defaultArg birthDate System.DateTime.MinValue
Now we can write:
let p1 = new Person(name="John", birthDate=DateTime.Now)
let p2 = new Person(name="John")
The code requires you to specify the name, but birthday is an optional argument with some default value.
You can also omit the new keyword and use less verbose syntax:
let p = Person(BirthDate = DateTime.Now, Name = "John")
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/members/constructors