I have 3 classes mapped with Entity Framework
public class A
{
public string Name { get; set; }
}
public class B
{
public string Name { get; set; }
public A A { get; set; }
}
public class C
{
public string Name { get; set; }
}
I have this Linq To Entities Where Condition
return queryableOfB.Where(b => b.A.Name = instanceOfC.Name);
Because this is a repetitive method in my logic, I want to create a method as:
protected void GetFilter<B, TBProperty, TCProperty>(
IQueryable<B> queryofB, C cModel,
Expression<Func<B, TBProperty>> bExpression,
Expression<Func<C, TCProperty>> cExpression)
{
var bExpValue = cExpression.Compile()(cModel);
queryofB.Where(b => b.Property.EndsWith(bExpValue)); // How can I compare two expressions? but adding "for example" an .EndsWith to expression 1?
}
It's important not to pass the .EndsWith in the expression because the decision of using EndsWith, StartsWith, Contains or exact comparison must be done in the method.
Thank you in advance Gurus.
actually where method expect function as predicate. you can try with below one.
its doing nothing just calling the where Extension method. its better to use there where method inline. But telling u the way how can u do it.
static IEnumerable<T1> M<T1>(IEnumerable<T1> objEnumerable, Func<T1, bool> wherePredicate)
{
return objEnumerable.Where(predicate);
}
// calling like
var listOfBObjects = GetBObjectIEnumerable();
C instanceOfC = GetCClassObject();
M<B>(listOfBObjects, b => b.A.Name = instanceOfC.Name);
update
you can use the
M<B>(listOfBObjects, b => b.A.Name.Equals(instanceOfC.Name));
M<B>(listOfBObjects, b => b.A.Name.StartsWith(instanceOfC.Name));
M<B>(listOfBObjects, b => b.A.Name.Contains(instanceOfC.Name));
to improve the performance and all. yes you can use the IQueryable rather than IEnumerable
Related
I have to distinct list of object but NOT only by ID because sometimes two different objects have same ID.
I have class:
public class MessageDTO
{
public MessageDTO(MessageDTO a)
{
this.MsgID = a.MsgID;
this.Subject = a.Subject;
this.MessageText = a.MessageText;
this.ViewedDate = a.ViewedDate;
this.CreatedDate = a.CreatedDate;
}
public int? MsgID { get; set; }
public string Subject { get; set; }
public string MessageText { get; set; }
public System.DateTime? ViewedDate { get; set; }
public System.DateTime? CreatedDate { get; set; }
}
How I can distinct list of:
List<MessageDTO> example;
Thanks
Use LINQ.
public class MessageDTOEqualityComparer : EqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO a, MessageDTO b)
{
// your logic, which checks each messages properties for whatever
// grounds you need to deem them "equal." In your case, it sounds like
// this will just be a matter of iterating through each property with an
// if-not-equal-return-false block, then returning true at the end
}
public int GetHashCode(MessageDTO message)
{
// your logic, I'd probably just return the message ID if you can,
// assuming that doesn't overlap too much and that it does
// have to be equal on the two
}
}
Then
return nonDistinct.Distinct(new MessageDTOEqualityComparer());
You can also avoid the need for an extra class by overriding object.Equals(object) and object.GetHashCode() and calling the empty overload of nonDistinct.Distinct(). Make sure you recognize the implications of this decision, though: for instance, those will then become the equality-testing functions in all non-explicit scopes of their use. This might be perfect and exactly what you need, or it could lead to some unexpected consequences. Just make sure you know what you're getting into.
I you want to use other properties, you should implement IEqualityComparer interface. More on: msdn
class MsgComparer : IEqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO x, MessageDTO Oy)
{
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(MessageDTO m)
{
//it must br overwritten also
}
}
Then:
example.Distinct(new MsgComparer());
You could also overwrite Equals in MessageDTO class:
class MessageDTO
{
// rest of members
public override bool Equals(object obj)
{
// your stuff. See: http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
}
public override int GetHashCode()
{
}
}
Then it's enough:
example.Distinct();
You could use the extension method DistinctBy from the MoreLinq library:
string[] source = { "first", "second", "third", "fourth", "fifth" };
var distinct = source.DistinctBy(word => word.Length);
See here:
I recommend you using solution of #Matthew Haugen
In case you don't want to create a new class for that, there is a way to use LINQ by grouping you list by distinct field(s) then select the first item on this group. For example:
example.(e => new { e.MsgID, e.Subject }).Select(grp => grp.FirstOrDefault());
I have a case in my application where I create selects over an IQueryable in this manner:
myContext.Data
.Where(...)
.OrderBy(...)
.Select(p => new MyDataModel()
{
...
MyComplexProp = p.SomeProp.HasValue ? p.OtherProp.Name + " " + p.AnotherProp.Mark : p.EvenAnotherProp.Name,
...
});
Now, the assignment to MyComplexProp is used on multiple places and I'd like to extract it to a single place so I can reuse it. Does anyone have an idea on how to achieve this?
I cannot use a static method because the IQueryable must not be executed in this phase.
Add a new constructor to MyDataModel to take the entity as an argument and do the logic:
public class MyDataModel
{
public string MyComplexProp {get; set;}
//Include a default constructor
public MyDataModel()
{
}
//Include a default constructor
public MyDataModel(DataClass data)
{
MyComplexProp = data.SomeProp.HasValue ? data.OtherProp.Name + " " + data.AnotherProp.Mark : data.EvenAnotherProp.Name,
}
}
Then your linq would simplify to:
myContext.Data
.Where(...)
.OrderBy(...)
.AsEnumerable()
.Select(p => new MyDataModel(p));
Note the use of the AsEnumerable(). This will mean that the constructor can execute in memory, but you will still have deferred execution of the query.
To acheive full DB side execution you'll need the logic converted to an expression. You're probably into creating an expression tree.
I've already tested Extension Method for your question and It works.
Here is the sample code:
namespace MyExtensionMethods
{
//MyDataModel sample
public class MyDataModel
{
public int? SomeProp { get; set; }
public string OtherPropName { get; set; }
public string AnotherPropMark { get; set; }
public string EvenAnotherPropName { get; set; }
}
//The extension Method
public static class ExtensionMethod
{
public static string ToMyComplexProp(this MyDataModel p)
{
return p.SomeProp.HasValue ? p.OtherPropName + " " + p.AnotherPropMark : p.EvenAnotherPropName;
}
}
public class TestClass
{
MyDataModel myDataModel;
public TestClass()
{
myDataModel = new MyDataModel();
//This is the extension method and it's working
myDataModel.ToMyComplexProp();
}
}
}
If you tried extension methods and it didn't work for you, the you declared it incorrectly. The soul purpose of extension method is for situations like this (Like how Linq is using it).
I suggest you to check MSDN Extension Method example to use it properly.
I want to convert Expression<Func<DTOItem, bool>> predicate to Expression<Func<Item, bool>> predicate with entity framework where DTOItem is mapped class of entity and Item(a table in database) is entityframe work class.
IDTOItemRepository itemRepo = new DTOItemRepository();
DTOItem itemObject = itemRepo.Single(q => q.ItemID == 1 && q.ItemType == 1);
where q => q.ItemID == 1 && q.ItemType == 1 is of type Expression<Func<DTOItem, bool>>.
Now i need to convert this expression to Expression<Func<Item, bool>>
You can't. You can do the opposite easily enough.
Let's take a look at another example.
I promise that if you give me an apple, I can tell you if it's still fresh. I know everything there is to know about every single kind of apple.
How can you use my knowledge to determine if any given piece of fruit is still fresh? You can't. I know about apples, but I don't know about other types of fruit. I can't make the guarantee that if you give me any kind of fruit I'll know if its fresh or not.
Now what if you were asked to determine if any type of Red Delicious apple is fresh? Can you use the information I can give you to provide an answer to that question in all cases? Sure you can. I can handle any kind of apple, limiting your questions to just one kind is no problem for me.
You have a function that knows how to take any DTOItem and return a boolean. You can't use that to take an Item at all and return a boolean, because what if that item isn't a DTOItem? Then what will you do? But if you have a method that can take any item at all and return a boolean then by all means you can "pretend" that it only accepts DTOItems. It can handle any item, limiting it's input to just DTOItems isn't a problem.
Use AutoMapper and it's Queryable Extensions portion, it will do exactly that for you (but not in a direct way). What it does is let you turn a IQueryable<Item> to a IQueyable<DtoItem> so you could use your Expression<Func<DTOItem, bool>> on it, then when you go to perform the query aginst the backing store AutoMapper will transform the Expression<Func<DTOItem, bool>> portion in to a Expression<Func<Item, bool>> portion to be passed on to the EF provider.
public static void Main(string[] args)
{
//This needs to be done once when your program starts up.
//You may need to do a more complicated "CreateMap" depending on how Item and DTOItem relate.
Mapper.CreateMap<Item, DTOItem>();
RunMyProgram();
}
public DTOItem GetItem()
{
using (var context = new MyDatabaseContext())
{
IQueryable<Item> itemQuery = context.Items;
return itemQuery.Project().To<DTOItem>()
.Single(q => q.ItemID == 1 && q.ItemType == 1);
}
//the above translates to the equivalent code
/*
return itemQuery.Where(q => q.itemid == 1 && q.itemtype == 1)
.Select(a => new ItemDTO {ItemID = a.itemid, ItemType = a.itemType, SomeType = a.sometype} )
.Single();
*/
}
public class DTOItem
{
public int ItemID { get; set; }
public int ItemType { get; set; }
public String SomeType {get; set;}
}
public class Item
{
public int itemid { get; set; }
public string itemtype { get; set; }
public String sometype {get; set;}
}
public class MyDatabaseContext: DbContext
{
public MyDatabaseContext(): base()
{
}
public DbSet<Item> Items{ get; set; }
}
how can i compare 2 lists and have the not matching items but according to the specifics properties
public partial class Cable : StateObject
{
public int Id { get; set; }
public int CablePropertyId { get; set; }
public int Item { get; set; }
public int TagNo { get; set; }
public string GeneralFormat { get; set; }
public string EndString { get; set; }
public string CableRevision { get; set; }
}
I want to comparision accomplished accoring to the CablePropertyId,TagNo and CableRevision, if i use
var diffCables = sourceCables.Except(destinationCables).ToList();
the whole properties are compared to each other . how can i do that?
Use Linq except method with custom EqualityComparer.
http://msdn.microsoft.com/en-us/library/bb336390(v=vs.110).aspx
class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable x, Cable y)
{
return (x.CablePropertyId == y.CablePropertyId && ...);
}
public int GetHashCode(Cable x) // If you won't create a valid GetHashCode based on values you compare on, Linq won't work properly
{
unchecked
{
int hash = 17;
hash = hash * 23 + x.CablePropertyID;
hash = hash * 23 + ...
}
return hash;
}
}
var diffCables = sourceCables.Except(destinationCables, new CableComparer());
Also, ToList() operation on the result isn't really necessary. Most of the time you can just operate on the result of Linq query IEnumerable without specifying the exact type; this way you won't waste performance on unneeded ToList() operation.
By the way, a couple of others proposed Where-based queries with simple lambda. Such solution is easier to read (in my opinion), but it's also less optimized: it forces n^2 checks, while IEqualityComparer allows Linq to be more optimal because of GetHashCode() method. Here's a great answer on importance of GetHashCode, and here's a great guide on writing GetHashCode() override.
You can create your own IEqualityComparer<Cable> like this:
public class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable x, Cable y)
{
return x.CablePropertyId == y.CablePropertyId &&
x.TagNo == y.TagNo &&
x.CableRevision == y.CableRevision;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Cable x)
{
return x.CablePropertyId ^
x.TagNo.GetHashCode() ^
x.CableRevision.GetHashCode();
}
}
Then use this overload of Except:
var comparer = new CableComparer();
var diffCables = sourceCables.Except(destinationCables, comparer).ToList();
Alternatively, the MoreLINQ library (also available on NuGet) provides a convenient ExceptBy method:
var diffCables = sourceCables.ExceptBy(
destinationCables,
x => new {
x.CablePropertyId,
x.TagNo,
x.CableRevision
})
.ToList();
You can override the Equals and GetHashCode methods of Cable if you will always compare this object in this manner.
Otherwise you can write a custom comparer and use the overload for .Except
List.Except Method
I think you can use something like this:
sourceCables.Where(sc => !destinationCables.Any(dc => dc.CablePropertyId == sc.CablePropertyId && ...));
Essentially, when you want to compare your own types, you'll need to describe how they compare/differ from each other. Linq wouldn't know which properties in your Cable class are different right?
So you build a comparer which can be used generally to compare two types.
In this case, two Cable instances:
class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable c1, Cable c2)//these represent any two cables.
{
if (c1.Height == c2.Height && ...)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(Cable c)
{
//this will work if each ID is unique
return c.Id.GetHashCode();
//otherwise you do this:
//return (c.Id ^ c. CablePropertyId).GetHashCode();
}
}
Then:
IEnumerable<Cable> except =
sourceCables.Except(destinationCables, new CableComparer());
If you use LINQ with IQueryable<>, there may be solution with Where()
var destinationCablesAnon = destinationCables.Select(a=>new {a.CablePropertyId, a.TagNo ,a.CableRevision}); // add ToArray() if use IEnumerable<>
var diffCables = sourceCables.Where(a=>!destinationCables.Contains(new {a.CablePropertyId, a.TagNo ,a.CableRevision})).ToList();
I'm not certain of the terminology so forgive my lack of clarity: Given a List<someclass> collection, can one create an extension method utilizing refection that allows one to return an array of specific class members/properties in the list collection by using the properties name? I realize the internal types may vary but the extension method would return the correct type.
public class someClass
{
public someClass(UInt32 _someInt, Double _someDouble, String _someString)
{
someInt = _someInt;
someDouble = _someDouble;
someString = _someString;
}
public UInt32 someInt { get; set; }
public Double someDouble { get; set; }
public String someString { get; set; }
}
...
List<someClass> listOfClasses = new List<someClass>();
listOfClasses.Add(new someClass(...));
listOfClasses.Add(new someClass(...));
listOfClasses.Add(new someClass(...));
//an extension function that does something like this
object[] propDouble = listOfClasses.ToArray("someDouble");
var propDouble = listOfClasses.Select(x => typeof(someClass)
.GetProperty("someDouble")
.GetValue(x)).ToArray();
Does this not satisfy what you want???
List<someclass> L;
IEnumerable<DesiredPropertyType> Properties =
L.Select(Item => Item.DesiredProperty).ToArray();
Short answer: Yes
How:
object[] propDouble = listOfClasses.Select(o => o.GetType()
.GetField("someDouble")
.GetValue(o)).ToArray();
You can convert this to an Extension Method easily.