I am creating a WPF application that tracks a directory on a user's computer. The application downloads files from a controlled directory and then saves some information in SQLite db. Part of the business process is not to re-process files that have already been downloaded, and to re-upload files that have been downloaded but changed since the last upload.
I have two helper methods that build and return the List<FileMetaData>
that I used LINQ - Full Outer Join to join. My problem is that the code does not work when I use my FileMetaData
object. Everything seems to work, but I don’t understand why it doesn’t work. Usually I try to post a comment in another thread, but currently I don't have "Rep".
Below is a sample that I created that shows my problem if you run it on LINQpad . Before you press the start button, make sure that you set the language as "C # Program". What should I do differently so that the sample works with objects? Thanks a ton!
void Main() { var dbItems = new List<FileMetaData>() { new FileMetaData {FilePath = "C:\\Foo.txt", DbTimestamp = "1" }, new FileMetaData {FilePath = "C:\\FooBar.txt", DbTimestamp = "3" }, }; var fsItems = new List<FileMetaData>() { new FileMetaData {FilePath = "C:\\Bar.txt", FsTimestamp = "2" }, new FileMetaData {FilePath = "C:\\FooBar.txt", FsTimestamp = "3" }, }; var leftOuter = from d in dbItems join f in fsItems on d.FilePath equals f.FilePath into temp from o in temp.DefaultIfEmpty(new FileMetaData(){}) select new FileMetaData { FilePath = d.FilePath, DbTimestamp = d.DbTimestamp, FsTimestamp = o.FsTimestamp, }; var rightOuter = from f in fsItems join d in dbItems on f.FilePath equals d.FilePath into temp from o in temp.DefaultIfEmpty(new FileMetaData(){}) select new FileMetaData { FilePath = f.FilePath, DbTimestamp = o.DbTimestamp, FsTimestamp = f.FsTimestamp, }; var full = leftOuter.AsEnumerable().Union(rightOuter.AsEnumerable()); leftOuter.Dump("Left Results"); rightOuter.Dump("Right Results"); full.Dump("Full Results"); }
EDIT:
The answer below was exactly what I was looking for. I implemented IEqualityComparer
as defined below and changed my call to var full = leftOuter.Union(rightOuter, new FileMetaDataCompare())
...
public class FileMetaDataCompare : IEqualityComparer<FileMetaData> { public bool Equals(FileMetaData x, FileMetaData y) { var areEqual = x.FilePath == y.FilePath; areEqual = areEqual && x.DbTimestamp == y.DbTimestamp; areEqual = areEqual && x.FsTimestamp == y.FsTimestamp; return areEqual; } public int GetHashCode(FileMetaData obj) { var hCode = string.Concat(obj.FilePath, obj.DbTimestamp, obj.FsTimestamp); return hCode.GetHashCode(); } }