Program.cs

153 lines | 4.283 kB Blame History Raw Download
using System;

using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.IO;
using System.Diagnostics;

using Microsoft.EntityFrameworkCore;

using Calibre.Model.Database;
using Calibre.Model.Database.Entities;

namespace Calibre
{
    class Program
    {
        private static string[] SelectDbFiles(DirectoryInfo directory)
        {
            var dbFiles = directory
                .GetFiles("metadata.db", SearchOption.AllDirectories)
                .Select(e => e.FullName)
                .ToArray();

            return dbFiles;
        }

        private static string BuildConnectionStringFromPath(string path)
        {
            return $"Filename={path}";
        }

        private static async Task<Dictionary<string, Book[]>> SearchBooksByTitle(
            string[] connectionStrings,
            string containsTitle
            )
        {
            List<CalibreContext> contexts 
                = new List<CalibreContext>(connectionStrings.Length);
            Dictionary<string, Task<Book[]>> data 
                = new Dictionary<string, Task<Book[]>>(connectionStrings.Length);

            try
            {
                foreach (var elem in connectionStrings)
                {
                    var context = new CalibreContext(elem);
                    contexts.Add(context);

                    IQueryable<Book> selectExpr = context
                        .Books
                        .Include(e => e.Tags)
                        .ThenInclude(e => e.TagItem);

                    if (string.IsNullOrEmpty(containsTitle))
                    {
                        selectExpr = selectExpr
                            .Where(
                                e => e.Title.Contains(containsTitle)
                            );
                    }

                    var selectResultTask = selectExpr.ToArrayAsync();
                    data.Add(elem, selectResultTask);
                }

                await Task.WhenAll(
                    data.Values.ToArray()
                    );
            }
            finally 
            {
                contexts.ForEach(
                    e => e.Dispose()
                    );
            }

            var result = data
                .ToDictionary(
                    e => e.Key, 
                    e => e.Value.Result
                    );
            return result;
        }

        static void Main(string[] args)
        {
            //var connectionString = @"";

            //using (var context = new CalibreContext(connectionString))
            //{
            //    var books = context.Books
            //        .OrderBy(e => e.Id)
            //        .ToArray();
            //}


            SearchByTitleInDirectory(
                new DirectoryInfo(@""),
                ""
                )
                .GetAwaiter()
                .GetResult();
        }


        static async Task SearchByTitleInDirectory(
            DirectoryInfo directory, 
            string containsTitle
            )
        {
            var watch = Stopwatch.StartNew();

            var dbFiles = SelectDbFiles(directory);
            var connectionStrings = dbFiles
                .Select(
                    e => BuildConnectionStringFromPath(e)
                )
                .ToArray();

            var searchResult = await SearchBooksByTitle(connectionStrings, "")
                .ConfigureAwait(false);
            watch.Stop();


            var allBooks = searchResult
                .SelectMany(e => e.Value)
                .ToArray();

            var allTags = allBooks
                .SelectMany(e => e.Tags)
                .Select(e => e.TagItem)
                .Distinct()
                .ToHashSet();

            var searchIgnoreCase = allBooks
                .Where(
                    e => 
                        e.Title.Contains(containsTitle, StringComparison.OrdinalIgnoreCase)
                        || e.Tags.Any(
                                e => e.TagItem.Name.Contains(containsTitle, StringComparison.OrdinalIgnoreCase)
                                )
                    )
                .ToArray();

            foreach (var elem in searchIgnoreCase)
            {
                Console.WriteLine($"{elem.Title}|{elem.AuthorSort}");
            }
        }
    }
}