Wednesday, 17 June 2020

C# - LINQ - IncludeFilter


LINQ –  IncludeFilter

EF, "Include" method is often used to load related entities / child collections. However, the method doesn't let you use LINQ queryable methods like Where to filter entities to include which is a major drawback. Excluding soft deleted records or limiting the result is a frequent real-life scenario which the "Include" method doesn't support.
EF+ Query IncludeFilter lets you filter and perform LINQ queryable methods on related entities.

// using Z.EntityFramework.Plus; // Don't forget to include this.
var ctx = new EntitiesContext();

// LOAD orders and the first 10 active related entities.
var list = ctx.Orders.IncludeFilter(x => x.Items.Where(y => !y.IsSoftDeleted)
                                               .OrderBy(y => y.Date)
                                               .Take(10))
                     .ToList();

Behind the code

Step 1 - Custom Queryable

The first time IncludeFilter is called, a custom Queryable and Provider are created for your query and will be used to append all queries.

Step 2 - Iterate or Execute

When an immediate method is invoked to resolve the query, the initial query is modified to create a new query which includes related entities.
  • The iterate method is invoked when it is possible to return multiple results like ToList() and ToArray()
  • The execute method is invoked when it is possible to return only one result like First() and Last()

Original Query:

var list = ctx.Orders.IncludeFilter(x => x.OrderItems.Where(y => !y.IsSoftDeleted))
                     .Take(10)
                     .ToList();

Executed Query:

var q1 = ctx.Orders.Take(10)
var p1 = q1.Select(x => x.OrderItems.Where(y => !y.IsSoftDeleted));
 
var list = q1.Select(x => new { x, p1 }).ToList().Select(x => x.X);

Query IncludeFilter - Load one level

// using Z.EntityFramework.Plus; // Don't forget to include this.
var ctx = new EntitiesContext();
 
// LOAD blogs and related active posts.
var blogs = ctx.Blogs.IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted)).ToList();

Query IncludeFilter - Load multiple levels

// using Z.EntityFramework.Plus; // Don't forget to include this.
var ctx = new EntitiesContext();
 
// LOAD blogs and related active posts and comments.
var blogs = ctx.Blogs.IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted))
                     .IncludeFilter(x => x.Posts.Where(y => !y.IsSoftDeleted)
                                                .Select(y => y.Comments
                                                              .Where(z => !z.IsSoftDeleted)))
                     .ToList();


Tuesday, 16 June 2020

C# - Files and Folders

// Directory of Window Form Application
string appPath = Path.GetDirectoryName(Application.ExecutablePath);

// Directory of Any Loaded Assembly
string path = Path.GetDirectoryName(Assembly.GetAssembly(typeof(MyClass)).CodeBase);


File Stream – Open Files
//Open existing file for read and write
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.Open))
{
   
}

//Open existing file for reading
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.Open, FileAccess.Read))
{
  
}

//Open existing file for writing
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.Open, FileAccess.Write))
{
  
}

//Open file for writing(with seek to end), if the file doesn't exist create it
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.Append))
{
   
}

//Create new file and open it for read and write, if the file exists overwrite it
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.Create))
{
  
}

//Create new file and open it for read and write, if the file exists throw exception
using (var fileStream = new FileStream(@"c:\file.txt", FileMode.CreateNew))
{
   
}

File Stream – Read Text Files
//Read Text File into String
//It's super easy to read whole text file into string using static class File and its method File.ReadAllText.
string text = File.ReadAllText(@"c:\file.txt", Encoding.UTF8);
           
//Read Text File into String(with StreamReader)
string text;
var fileStream = new FileStream(@"c:\file.txt", FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
    text = streamReader.ReadToEnd();
}

File Stream – Load Text from Files To String
//Read Text File into String Array
//Again, the easy way is to use static class File and it's method File.ReadAllLi­nes.
string[] lines = File.ReadAllLines(@"c:\file.txt", Encoding.UTF8);

//Read Text File into String Array(with StreamReader)
string[] lines;
var list = new List<string>();
var fileStream = new FileStream(@"c:\file.txt", FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        list.Add(line);
    }
}
lines = list.ToArray();
           
//Read Text File Line by Line
foreach (string line in File.ReadLines(@"c:\file.txt", Encoding.UTF8))
{
    // process the line
}

//Read Text File Line by Line(with StreamReader)
var fileStream = new FileStream(@"c:\file.txt", FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        // process the line
    }
}

//To load text from file to string you can use StreamReader.
string text;
using (var streamReader = new StreamReader(@"c:\file.txt", Encoding.UTF8))
{
    text = streamReader.ReadToEnd();
}


Get File from Directory 
//Get files from directory
//Method Directory.GetFiles returns string array with files names(full paths).
string[] filePaths = Directory.GetFiles(@"c:\MyDir\");

//Get files from directory (with specified extension)
string[] filePaths = Directory.GetFiles(@"c:\MyDir\", "*.bmp");

//Get files from directory(including all subdirectories)
//If you want to search also in subfolders use parameter SearchOption.A­llDirectories.
string[] filePaths = Directory.GetFiles(@"c:\MyDir\", "*.bmp", SearchOption.AllDirectories);



Delete All Files       
//Delete all files
string[] filePaths = Directory.GetFiles(@"c:\MyDir\");
foreach (string filePath in filePaths)
    File.Delete(filePath);

//Delete all files(one - row example)
//To delete all files using one code line, you can use Array.ForEach with combination of anonymous method.
Array.ForEach(Directory.GetFiles(@"c:\MyDir\"),
              delegate (string path) { File.Delete(path); });

//Directory of windows forms application(.exe)
string appPath = Path.GetDirectoryName(Application.ExecutablePath);

//Directory of any loaded assembly(.exe or .dll)
string path = Path.GetDirectoryName(
                     Assembly.GetAssembly(typeof(MyClass)).CodeBase);


File Attributes – How To Get Or Set File Attributes
//Get file attributes
string filePath = @"c:\test.txt";
FileAttributes fileAttributes = File.GetAttributes(filePath);

//Set file attributes
File.SetAttributes(filePath, FileAttributes.Normal);
File.SetAttributes(filePath, FileAttributes.Archive | FileAttributes.ReadOnly);


// check whether a file is read only
bool isReadOnly = ((File.GetAttributes(filePath) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);

// check whether a file is hidden
bool isHidden = ((File.GetAttributes(filePath) & FileAttributes.Hidden) == FileAttributes.Hidden);

// check whether a file has archive attribute
bool isArchive = ((File.GetAttributes(filePath) & FileAttributes.Archive) == FileAttributes.Archive);

// check whether a file is system file
bool isSystem = ((File.GetAttributes(filePath) & FileAttributes.System) == FileAttributes.System);

//Add file attributes to current ones
File.SetAttributes(filePath, File.GetAttributes(filePath) | FileAttributes.Hidden);

//Set (add) both archive and read only attributes
File.SetAttributes(filePath, File.GetAttributes(filePath) | (FileAttributes.Archive | FileAttributes.ReadOnly));

//Delete/clear file attributes from current ones
File.SetAttributes(filePath, File.GetAttributes(filePath) & ~FileAttributes.Hidden);

//Delete/clear archive and read only attributes
File.SetAttributes(filePath, File.GetAttributes(filePath) & ~(FileAttributes.Archive | FileAttributes.ReadOnly));



File Stream – Read Files
//Read file using FileStream
//First create FileStream to open a file for reading.
//Then call FileStream.Read in a loop until the whole file is read.
//Finally close the stream.
public static byte[] ReadFile(string filePath)
{
    byte[] buffer;
    FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    try
    {
        int length = (int)fileStream.Length;  // get file length
        buffer = new byte[length];            // create buffer
        int count;                            // actual number of bytes read
        int sum = 0;                          // total number of bytes read

        // read until Read method returns 0 (end of the stream has been reached)
        while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
            sum += count;  // sum is a buffer offset for next reading
    }
    finally
    {
        fileStream.Close();
    }
    return buffer;
}