Entity framework, compare complex types - c#

How do I compare complex types in queries?
Does not work (always returns null, EDIT: since new version of EF it throws exception):
DbVector3 pos = new DbVector3() { X = 0, Y = 0, Z = 0};
db.PhysObjects.FirstOrDefault(s => s.Position == pos);
Works:
DbVector3 pos = new DbVector3() { X = 0, Y = 0, Z = 0};
db.PhysObjects.FirstOrDefault(s => s.Position.X == pos.X && s.Position.Y == pos.Y && s.Position.Z == pos.Z);
Is there any way to make first example working?
EDIT:
Sorry, I probably mention only in title that this is entity framework.
db is ObjectContext, PhysObjects is ObjectSet<>

You need to override the Equals function in your DbVector class, so that when comparisons are made it will be used to compare 2 objects.
protected override bool Equals(object comparer)
{
DbVector3 compareObj = obj as DbVector3;
return compareObj.X == this.X && compareObj.Y == this.Y && compareObj.Z == this.Z;
}
You can also do the same for the == and != operators. Something similar to below :
public static bool operator ==(DbVector3 a, DbVector3 b)
{
return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
}
public static bool operator !=(DbVector3 a, DbVector3 b)
{
return !(a == b);
}
Have a read of MSDN - Guidelines for Overriding for more information.

No, it's not supported, unless both values are in database.

Related

Is there a faster way to compare these decimals?

I have a stream of decimals and I am trying to compare the most recent decimal to the difference of the last 6 decimals, I may increase this number
I have the following class
public class CompareRandom
{
private const decimal DIFFERENCE = 1.8m;
public decimal a;
public decimal b;
public decimal c;
public decimal d;
public decimal e;
public decimal f;
public decimal g;
public bool Compare(decimal num)
{
this.g = this.f;
this.f = this.e;
this.e = this.d;
this.d = this.c;
this.c = this.b;
this.b = this.a;
this.a = num;
if (b != decimal.Zero && b / DIFFERENCE > a)
{
return true;
}
if (c != decimal.Zero && c / DIFFERENCE > a)
{
return true;
}
if (d != decimal.Zero && d / DIFFERENCE > a)
{
return true;
}
if (e != decimal.Zero && e / DIFFERENCE > a)
{
return true;
}
if (f != decimal.Zero && f / DIFFERENCE > a)
{
return true;
}
if (g != decimal.Zero && g / DIFFERENCE > a)
{
return true;
}
return false;
}
}
Then I initialize it as volatile
volatile static CompareRandom CompareRandom = new CompareRandom();
Then I call CompareRandom.Compare(value) synchronously as part of a loop that updates every 1ms to compare the values.
The part I am the most interested in knowing if there is a faster way to do is this part
this.g = this.f;
this.f = this.e;
this.e = this.d;
this.d = this.c;
this.c = this.b;
this.b = this.a;
this.a = num;
A successful answer will demonstrate a faster execution of the method Compare
See if you can make it faster:
https://dotnetfiddle.net/tLw8qM
https://dotnetfiddle.net/jd0bSF
You don't need to perform the division every time. Instead, multiply a by DIFFERENCE to obtain a threshold:
// Name changed to be more conventional
private const decimal Difference = 1.8m;
public bool Compare(decimal num)
{
g = f;
f = e;
e = d;
d = c;
c = b;
b = a;
a = num;
var threshold = num * Difference;
return (b != decimal.Zero && b > threshold) ||
(c != decimal.Zero && c > threshold) ||
(d != decimal.Zero && d > threshold) ||
(e != decimal.Zero && e > threshold) ||
(f != decimal.Zero && f > threshold) ||
(g != decimal.Zero && g > threshold);
};
As asides:
It's odd for a Compare method to return bool rather than an integer; given that it's not the "common" meaning of Compare, it's probably worth renaming it for clarity
It's very odd for a comparison method to change the state of an object, as this is doing (assigning to a) - another good reason to change the name.
Using a collection instead of separate variables would make all of this more maintainable, but I'd be surprised if it improved the speed.
I also really like the idea of eliminating the division, but I don't like the way you're handling booleans: the original question says something like:
if condition1 then return true;
if condition2 then return true;
if condition3 then return true;
If condition1 is true, then the code does not bother about the calculation of the other conditions (why would it, when one condition is true, then the OR of all conditions also is true).
The proposal from Jon looks as follows:
return (condition1 || condition2 || condition3)
This does exactly the same thing, but the fact if the calculation of the OR equation is determined by the compiler: if you're dealing with an older compiler, not performing optimsation, then the entire calculation is done, even if condition1 is true.

Sorting based on multiple fields using IComparer [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I use the below code to sort List<DataAccessViewModel> list.
Here is the sort order :
PriorityScore
MName
CName
FName
It works as expected.
public int Compare(DataAccessViewModel x, DataAccessViewModel y)
{
if (x == null || y == null)
{
return 0;
}
return x.CompareTo(y);
}
public int CompareTo(DataAccessViewModel mod)
{
int retval = (int)(this.PriorityScore?.CompareTo(mod.PriorityScore));
if(retval != 0)
return retval;
else
{
retval = (this.MName ?? "zzzzzzzzzzzzz").CompareTo(mod.MName ?? "zzzzzzzzzzzzz");
if (retval != 0)
return retval;
else
{
retval = (this.CName ?? "zzzzzzzzzzzzz").CompareTo(this.CName ?? "zzzzzzzzzzzzz");
if (retval != 0)
return retval;
else
retval = (this.FName ?? "zzzzzzzzzzzzz").CompareTo(this.FName ?? "zzzzzzzzzzzzz");
}
}
return retval;
}
But the code looks clunky to me. Is there any better way of doing it or is this it ?
There's a issue in the current code:
public int Compare(DataAccessViewModel x, DataAccessViewModel y)
{
if (x == null || y == null)
{
return 0;
}
...
Since null equals to any value then all values are equal:
a == null, null == b => a == b
It's not the rule you want to implement. I suggest something like this
using System.Linq;
...
// static: we don't want "this"
public static int TheCompare(DataAccessViewModel x, DataAccessViewModel y) {
// Special cases, nulls
if (ReferenceEquals(x, y)) // if references are shared, then equal
return 0;
if (null == x) // let null be smaller than any other value
return -1;
if (null == y)
return 1;
// How we compare strings
static int MyCompare(string left, string right) =>
ReferenceEquals(left, right) ? 0
: null == left ? 1 // null is greater than any other string
: null == right ? -1
: string.Compare(left, right);
// Func<int> for lazy computation
return new Func<int>[] {
() => x.PriorityScore?.CompareTo(y.PriorityScore) ?? -1,
() => MyCompare(x.MName, y.MName),
() => MyCompare(x.CName, y.CName),
() => MyCompare(x.FName, y.FName),
}
.Select(func => func())
.FirstOrDefault(value => value != 0);
}
And then for interface we have
public int CompareTo(DataAccessViewModel other) => TheCompare(this, other);
// I doubt if you want to implement both IComparable<T> and
// IComparer<T> but you can easily do it
public int Compare(DataAccessViewModel x, DataAccessViewModel y) =>
TheCompare(x, y);
You're almost there: just skip the else statements which follow a return:
public int CompareTo(DataAccessViewModel mod)
{
// I worry about this line -- if you're sure that PriorityScore is not null,
// why not use this.PriorityScore.Value to make that clear?
int retval = (int)(this.PriorityScore?.CompareTo(mod.PriorityScore));
if (retval != 0)
return retval;
retval = (this.MName ?? "zzzzzzzzzzzzz").CompareTo(mod.MName ?? "zzzzzzzzzzzzz");
if (retval != 0)
return retval;
retval = (this.CName ?? "zzzzzzzzzzzzz").CompareTo(this.CName ?? "zzzzzzzzzzzzz");
if (retval != 0)
return retval;
return (this.FName ?? "zzzzzzzzzzzzz").CompareTo(this.FName ?? "zzzzzzzzzzzzz");
}
You can also handle the nullables properly by using Comparer<T>.Default. This will sort null as equal to other null values, but less than any other object.
public int CompareTo(DataAccessViewModel mod)
{
int retval = Comparer<int?>.Default.Compare(this.PriorityScore, mod.PriorityScore);
if (retval != 0)
return retval;
retval = Comparer<string>.Default.Compare(this.MName, mod.MName);
if (retval != 0)
return retval;
retval = Comparer<string>.Default.Compare(this.CName, mod.CName);
if (retval != 0)
return retval;
return Comparer<string>.Default.Compare(this.FName, mod.FName);
}
Consider leveraging the default behavior of ValueTuples:
IComparer (this should probably not be the same as your class)
public int Compare(DataAccessViewModel x, DataAccessViewModel y)
{
if (x == null && y == null)
{
return 0;
}
if (x == null) return -1;
if (y == null) return 1;
var thisCompareOrder = (x.PriorityScore, x.MName, x.CName, x.FName);
var thatCompareOrder = (y.PriorityScore, y.MName, y.CName, y.FName);
return thisCompareOrder.CompareTo(thatCompareOrder);
}
If you want your class to have these semantics by default, implement IComparable.
public int CompareTo(DataAccessViewModel mod)
{
if(mod == null) return 1;
var thisCompareOrder = (this.PriorityScore, this.MName, this.CName, this.FName);
var thatCompareOrder = (mod.PriorityScore, mod.MName, mod.CName, mod.FName);
return thisCompareOrder.CompareTo(thatCompareOrder);
}
You might also consider making your original class a record, which has value-based semantics by default.

How to implement “stencil” pattern using linq?

I have a list of points with x,y,z coordinates and “values” say ints. I want to select a new enumerable such that for each value will be equal to ‘value + value[up] +... + value[down]’ so a stencil that uses all surrounding values only if they exist. How to do such stencil pattern with linq?
How about this, create a method to say if two values are neigbours:
public class Class1
{
public int x;
public int y;
public int z;
public int myValue;
public static bool IsNeighbour(Class1 c1, Class1 c2)
{
bool ret = ((Math.Abs(c1.x - c2.x) == 1) && c1.y == c2.y && c1.z == c2.z) ||
((Math.Abs(c1.y - c2.y) == 1) && c1.x == c2.x && c1.z == c2.z) ||
((Math.Abs(c1.z - c2.z) == 1) && c1.y == c2.y && c1.x == c2.x);
return ret;
}
}
Then, you could call:
//lc is a List<Class1>;
var result = lc.Select(currItem =>
lc.Where(anItem =>
Class1.IsNeighbour(currItem, anItem)).Sum(item => item.myValue) + currItem.myValue);
For each item it'll select its neighbours, sum them up and add the current item value.
If your logic also consider diagonal elements or other thing, all you have to do is change IsNeighbour accordingly

Library with Equals and GetHashCode helper methods for .NET

Google Guava provides nice helpers to implement equals and hashCode like the following example demonstrates:
public int hashCode() {
return Objects.hashCode(lastName, firstName, gender);
}
Is there a similar library for Microsoft .NET?
I don't see why you'd need one. If you want to create a hash-code based on the default GetHashCode for 3 different items, then just use:
Tuple.Create(lastName, firstName, gender).GetHashCode()
That'll boil down to the equivalent of:
int h1 = lastName.GetHashCode();
int h2 = firstName.GetHashCode();
int h3 = gender.GetHashCode();
return (((h1 << 5) + h1) ^ (((h2 << 5) + h2) ^ h3));
Which is pretty reasonable for such a general-purpose combination.
Likewise:
Tuple.Create(lastName, firstName, gender).Equals(Tuple.Create(lastName2, firstName2, gender2))
Would boil down to the equivalent of calling:
return ((lastName == null && lastName2 == null) || (lastName != null && lastName.Equals(lastName2)))
&& ((firstName == null && firstName2 == null) || (firstName != null && firstName.Equals(lastName2)))
&& ((gender == null && gender2 == null) || (gender != null && gender.Equals(lastName2)));
Again, about as good as you could expect.
AFAIK none. However, writing your own shouldn't be too complex (nb using a variation of the Bernstein hash):
public static class Objects
{
public static bool Equals<T>(T item1, T item2, Func<T, IEnumerable<object>> selector)
{
if (object.ReferenceEquals(item1, item2) return true;
if (item1 == null || item2 == null) return false;
using (var iterator1 = selector(item1).GetEnumerator())
using (var iterator2 = selector(item2).GetEnumerator())
{
var moved1 = iterator1.MoveNext();
var moved2 = iterator2.MoveNext();
if (moved1 != moved2) return false;
if (moved1 && moved2)
{
if (!Equals(iterator1.Current, iterator2.Current)) return false;
}
}
return true;
}
public static bool Equals(object item1, object item2)
{
return object.Equals(item1, item2);
}
public static int GetHashCode(params object[] objects)
{
unchecked
{
int hash = 17;
foreach (var item in objects)
{
hash = hash * 31 + item.GetHashCode();
}
return hash;
}
}
}

Is this possible somehow in C# : if (a==b==c==d) {...}

Is there a quick way to compare equality of more than one values in C#?
something like:
if (5==6==2==2){
//do something
}
Thanks
if (a == b && b == c && c == d) {
// do something
}
In C#, an equality operator (==) evaluates to a bool so 5 == 6 evaluates to false.
The comparison 5 == 6 == 2 == 2 would translate to
(((5 == 6) == 2) == 2)
which evaluates to
((false == 2) == 2)
which would try to compare a boolwith an int. Only if you would compare boolean values this way would the syntax be valid, but probably not do what you want.
The way to do multiple comparison is what #Joachim Sauer suggested:
a == b && b == c && c == d
public static class Common {
public static bool AllAreEqual<T>(params T[] args)
{
if (args != null && args.Length > 1)
{
for (int i = 1; i < args.Length; i++)
{
if (args[i] != args[i - 1]) return false;
}
}
return true;
}
}
...
if (Common.AllAreEqual<int>(a, b, c, d, e, f, g))
This could help :)
No this is not possible, you have to split it into separate statements.
if(x == y && x == z) // now y == z
{
}
Good luck

Categories

Resources