Tân Nguyễn Tân Nguyễn - 24 days ago 5
C# Question

Sort 2 tables at the same time via using LinQ

My example contains 2 tables

Book
and
Comment
.

Book
:

Id Name UserId DateTime

B1 Book1 User1 16/11/2016 11:15:00
B2 Book2 User1 16/11/2016 12:15:00
B3 Book3 User2 16/11/2016 10:15:00


Comment
:

Id BookId UserId DateTime

C1 B3 User1 16/11/2016 11:17:00
C2 B1 User1 16/11/2016 11:16:00


List of
Book
via specific user id:

string userid = "User1";

IEnumerable<Book> books = _context.Books.Where(x => x.UserId == userid);


List of
Comment
:

IEnumerable<Book> comments = _context.Comments.Where(x => x.UserId == userid);


In activity history (web page), I want to show all
books
and
comments
what I have collected via
userid
, one by one. But, how can I sort 2 objects again via
.OrderByDescending(x => x.DateTime)
?

My goal:

User1
just postes a new book to the store:

B2 Book2 User1 16/11/2016 12:15:00


Before that, he posted a comment to his own thread:

C1 B1 User1 16/11/2016 11:17:00


Earlier, he posted a comment in another thread (
UserId == "User2"
):

C2 B3 User1 16/11/2016 11:16:00


Older, he posted a new book to the store:

B1 Book1 User1 16/11/2016 11:15:00


I can classify them via
DateTime
column (on paper):

16/11/2016 12:15:00
16/11/2016 11:17:00
16/11/2016 11:16:00
16/11/2016 11:15:00


How can I sort it?

UPDATE:

I just found a solution but LinQ. I want a solution using LinQ with same result (for shorter):

namespace MP
{
public class Book
{
public string Id { get; set; }

public string Name { get; set; }

public string UserId { get; set; }

public DateTime DateTime { get; set; }
}

public class Comment
{
public string Id { get; set; }

public string BookId { get; set; }

public string UserId { get; set; }

public string Content { get; set; }

public DateTime DateTime { get; set; }
}

public class Result
{
public object Object { get; set; }

public DateTime DateTime { get; set; }
}

class Program
{
static void Main()
{
try
{
string userid = "User1";

var books = new List<Book>();
books.Add(new Book { Id = "B1", Name = "Book1", UserId = "User1", DateTime = new DateTime(2016, 11, 16, 11, 15, 00) });
books.Add(new Book { Id = "B2", Name = "Book2", UserId = "User1", DateTime = new DateTime(2016, 11, 16, 12, 15, 00) });
books.Add(new Book { Id = "B3", Name = "Book3", UserId = "User2", DateTime = new DateTime(2016, 11, 16, 10, 15, 00) });

var comments = new List<Comment>();
comments.Add(new Comment { Id = "c1", BookId = "B3", UserId = "User1", Content = "cmt1", DateTime = new DateTime(2016, 11, 16, 11, 17, 00) });
comments.Add(new Comment { Id = "c2", BookId = "B1", UserId = "User1", Content = "cmt2", DateTime = new DateTime(2016, 11, 16, 11, 16, 00) });

var result = new List<Result>();
books.ForEach(x =>
{
if (x.UserId == userid)
{
result.Add(new Result { Object = x, DateTime = x.DateTime });
}
});

comments.ForEach(x =>
{
if (x.UserId == userid)
{
result.Add(new Result { Object = x, DateTime = x.DateTime });
}
});

result = result.OrderByDescending(x => x.DateTime).ToList();

foreach (var item in result)
{
Type type = item.Object.GetType();

if (type == typeof(MP.Book))
{
var book = (Book)item.Object;

Console.WriteLine($"Book: Id: {book.Id} - Name: {book.Name} - DateTime: {book.DateTime}");
}

if (type == typeof(MP.Comment))
{
var cmt = (Comment)item.Object;

Console.WriteLine($"Comment: Id: {cmt.Id} - Content: {cmt.Content} - DateTime: {cmt.DateTime}");
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}


Result:

1

Answer

Here's solution that should work for you. Basically I took your idea of objectifying the data and creating a linq query that creates a list of objects from each list and sorts them according to the DateTime. By overriding the ToString() method printing the contents of the list becomes very simple:

public class Book
{
    public const string className = "Book";
    public string Id { get; set; }

    public string Name { get; set; }

    public string UserId { get; set; }

    public DateTime DateTime { get; set; }

    public override string ToString()
    {
        return $"Book:    Id: {Id.PadRight(7)} - Name: {Name.PadRight(14)} - DateTime: {DateTime}";
    }

}

public class Comment
{
    public string Id { get; set; }

    public string BookId { get; set; }

    public string UserId { get; set; }

    public string Content { get; set; }

    public DateTime DateTime { get; set; }

    public override string ToString()
    {
        return $"Comment: Id: {Id.PadRight(7)} - Content: {Content.PadRight(11)} - DateTime: {DateTime}";
    }

}

class Program
{
    static void Main()
    {
        try
        {
            string userid = "User1";

            var books = new List<Book>();
            books.Add(new Book { Id = "B1", Name = "Book1", UserId = "User1", DateTime = new DateTime(2016, 11, 16, 11, 15, 00) });
            books.Add(new Book { Id = "B2", Name = "Book2", UserId = "User1", DateTime = new DateTime(2016, 11, 16, 12, 15, 00) });
            books.Add(new Book { Id = "B3", Name = "Book3", UserId = "User2", DateTime = new DateTime(2016, 11, 16, 10, 15, 00) });

            var comments = new List<Comment>();
            comments.Add(new Comment { Id = "c1", BookId = "B3", UserId = "User1", Content = "cmt1", DateTime = new DateTime(2016, 11, 16, 11, 17, 00) });
            comments.Add(new Comment { Id = "c2", BookId = "B1", UserId = "User1", Content = "cmt2", DateTime = new DateTime(2016, 11, 16, 11, 16, 00) });
            var test = (from b in books
                        where b.UserId == userid
                        select (object)b).Concat
                        (from c in comments
                        where c.UserId == userid
                        select (object)c).OrderBy(x => x.GetType() == typeof(Book)?((Book)x).DateTime:((Comment)x).DateTime);
            foreach(var o in test)
            {
                Console.WriteLine(o);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}