Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between == and .Equals() with Interfaces and LINQ

Tags:

c#

linq-to-sql

I recently got a "The mapping of interface member ..... is not supported" error, which I resolved based on this thread. To demonstrate:

public interface IMyInterface { string valueText { get; set; } }
public class MyData : IMyInterface
{
   int ID { get; set;}
   string valueText { get; set;}
}
public class MyOtherData : IMyInterface
{
   long ID { get; set;}
   string valueText { get; set;}
}

and

public static IEnumerable<T> GetByValue<T>(string value) : where T : class, IMyInterface, new()
{ 
   using (var context = new DataContext())
   { 
      // The important line
      return context.GetTable<T>().Where(x => x.valueText == value);
   }
}

Running this code, I'd get a NotSupportedException: "The mapping of interface member IMyInterface.valueText is not supported". However, if I replace the x.valueText == value with x.valueText.Equals(value), this works entirely as expected.

I've solved this in my code, but I want to understand why it behaves this way. Can anyone explain it?

Update: As per my comment below, the LINQ to SQL team closed this as a "Won't fix". I think that means it now counts as a known bug, but one that isn't going to be resolved any time soon. I'd still like to know why it behaves differently in the first place, though.

like image 345
Bobson Avatar asked Apr 11 '12 22:04

Bobson


1 Answers

Apparently the decision to push the query upstream to the server is made based on an incomplete set of rules, and then LINQ-to-SQL finds a construct (an interface) that it can't deal with.

The method call isn't supported by LINQ-to-SQL, so it generates a query to retrieve all records and then uses LINQ-to-Objects to filter them. (Actually, based on your other thread, LINQ-to-SQL may make a special exception for object.Equals and knows how to convert that to SQL).

LINQ-to-SQL probably should fall back to the LINQ-to-Objects behavior when an interface is involved, but apparently it just throws an exception instead.

like image 188
Ben Voigt Avatar answered Sep 21 '22 18:09

Ben Voigt