<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dmitry Pavlov</title>
    <description>The latest articles on DEV Community by Dmitry Pavlov (@dr_dimaka).</description>
    <link>https://dev.to/dr_dimaka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F159800%2Fe85c34c2-a5f5-4377-9359-416203e41a5d.jpg</url>
      <title>DEV Community: Dmitry Pavlov</title>
      <link>https://dev.to/dr_dimaka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dr_dimaka"/>
    <language>en</language>
    <item>
      <title>Tree Structure in EF Core: How to configure a self-referencing table and use it.</title>
      <dc:creator>Dmitry Pavlov</dc:creator>
      <pubDate>Tue, 25 Aug 2020 11:12:53 +0000</pubDate>
      <link>https://dev.to/dr_dimaka/tree-structure-in-ef-core-how-to-configure-a-self-referencing-table-and-use-it-122m</link>
      <guid>https://dev.to/dr_dimaka/tree-structure-in-ef-core-how-to-configure-a-self-referencing-table-and-use-it-122m</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vZ3YgpeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbgBnFCI19FGysvor11A9sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vZ3YgpeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AbgBnFCI19FGysvor11A9sg.png" alt="" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tree Structure in EF Core: How to configure a self-referencing table and use it.
&lt;/h3&gt;

&lt;p&gt;One of the very common questions I am getting from the .NET community is how to configure and use the tree structures in EF Core. This story is one of the possible ways to do it.&lt;/p&gt;

&lt;p&gt;The common tree structures are file tree, categories hierarchy, and so on. Let it be a folders tree for example. The entity class will be a Folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Folder
{
    public Guid Id { get; set; }
    public string Name { get; set; }      
    public Folder Parent { get; set; }
    public Guid? ParentId { get; set; }
    public ICollection&amp;lt;Folder&amp;gt; SubFolders { get; } = new List&amp;lt;Folder&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how to configure DB schema via overriding OnModelCreatingmethod of your DbContextclass. This could be done via configuration property attributes on our entity class, but I prefer to define DB schema this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity&amp;lt;Folder&amp;gt;(entity =&amp;gt;
    {
        entity.HasKey(x =&amp;gt; x.Id);
        entity.Property(x=&amp;gt; x.Name);
        entity.HasOne(x=&amp;gt; x.Parent)
            .WithMany(x=&amp;gt; x.SubFolders)
            .HasForeignKey(x=&amp;gt; x.ParentId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.Restrict);
    });

    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how to load data from DB as a tree of folders, flatten it as a plain list of folder “nodes”, and get some details related to tree structure like node level, node parents, etc.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    List&amp;lt;Folder&amp;gt; all = \_dbContext.Folders.Include(x =&amp;gt; x.Parent).ToList();

    TreeExtensions.ITree&amp;lt;Folder&amp;gt; virtualRootNode = all.ToTree((parent, child) =&amp;gt; child.ParentId == parent.Id);

    List&amp;lt;TreeExtensions.ITree&amp;lt;Folder&amp;gt;&amp;gt; rootLevelFoldersWithSubTree = virtualRootNode.Children.ToList();

    List&amp;lt;TreeExtensions.ITree&amp;lt;Folder&amp;gt;&amp;gt; flattenedListOfFolderNodes = virtualRootNode.Children.Flatten(node =&amp;gt; node.Children).ToList();

    // Each Folder entity can be retrieved via node.Data property:
    TreeExtensions.ITree&amp;lt;Folder&amp;gt; folderNode = flattenedListOfFolderNodes.First(node =&amp;gt; node.Data.Name == "MyFolder");

    Folder folder = folderNode.Data;
    int level = folderNode.Level;
    bool isLeaf = folderNode.IsLeaf;
    bool isRoot = folderNode.IsRoot;
    ICollection&amp;lt;TreeExtensions.ITree&amp;lt;Folder&amp;gt;&amp;gt; children = folderNode.Children;
    TreeExtensions.ITree&amp;lt;Folder&amp;gt; parent = folderNode.Parent;
    List&amp;lt;Folder&amp;gt; parents = GetParents(folderNode);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method demonstrates how to get all parents from the tree for specific node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static List&amp;lt;T&amp;gt; GetParents&amp;lt;T&amp;gt;(TreeExtensions.ITree&amp;lt;T&amp;gt; node, List&amp;lt;T&amp;gt; parentNodes = null) where T : class
{
    while (true)
    {
        parentNodes ??= new List&amp;lt;T&amp;gt;();

        if (node?.Parent?.Data == null) return parentNodes;

        parentNodes.Add(node.Parent.Data);

        node = node.Parent;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tree operation extension methods below and helper interface for wrapping any entity into the tree node object. So technically your entity can be any class where you have relation &lt;strong&gt;&lt;em&gt;parent-&amp;gt;children&lt;/em&gt;&lt;/strong&gt; (to get the plain list of nodes from the tree using Flatten) and &lt;strong&gt;&lt;em&gt;child-&amp;gt; parent&lt;/em&gt;&lt;/strong&gt; (to build the tree from the list using ToTreemethod):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static class TreeExtensions
{
    /// &amp;lt;summary&amp;gt; Generic interface for tree node structure &amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;
    public interface ITree&amp;lt;T&amp;gt;
    {
        T Data { get; }
        ITree&amp;lt;T&amp;gt; Parent { get; }
        ICollection&amp;lt;ITree&amp;lt;T&amp;gt;&amp;gt; Children { get; }
        bool IsRoot { get; }
        bool IsLeaf { get; }
        int Level { get; }
    }

    /// &amp;lt;summary&amp;gt; Flatten tree to plain list of nodes &amp;lt;/summary&amp;gt;
    public static IEnumerable&amp;lt;TNode&amp;gt; Flatten&amp;lt;TNode&amp;gt;(this IEnumerable&amp;lt;TNode&amp;gt; nodes, Func&amp;lt;TNode, IEnumerable&amp;lt;TNode&amp;gt;&amp;gt; childrenSelector)
    {
        if (nodes == null) throw new ArgumentNullException(nameof(nodes));

        return nodes.SelectMany(c =&amp;gt; childrenSelector(c).Flatten(childrenSelector)).Concat(nodes);
    }

    /// &amp;lt;summary&amp;gt; Converts given list to tree. &amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name="T"&amp;gt;Custom data type to associate with tree node.&amp;lt;/typeparam&amp;gt;
    /// &amp;lt;param name="items"&amp;gt;The collection items.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="parentSelector"&amp;gt;Expression to select parent.&amp;lt;/param&amp;gt;
    public static ITree&amp;lt;T&amp;gt; ToTree&amp;lt;T&amp;gt;(this IList&amp;lt;T&amp;gt; items, Func&amp;lt;T, T, bool&amp;gt; parentSelector)
    {
        if (items == null) throw new ArgumentNullException(nameof(items));

        var lookup = items.ToLookup(item =&amp;gt; items.FirstOrDefault(parent =&amp;gt; parentSelector(parent, item)),
            child =&amp;gt; child);

        return Tree&amp;lt;T&amp;gt;.FromLookup(lookup);
    }

    /// &amp;lt;summary&amp;gt; Internal implementation of &amp;lt;see cref="ITree{T}" /&amp;gt;&amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name="T"&amp;gt;Custom data type to associate with tree node.&amp;lt;/typeparam&amp;gt;
    internal class Tree&amp;lt;T&amp;gt; : ITree&amp;lt;T&amp;gt;
    {
        public T Data { get; }

        public ITree&amp;lt;T&amp;gt; Parent { get; private set; }

        public ICollection&amp;lt;ITree&amp;lt;T&amp;gt;&amp;gt; Children { get; }

        public bool IsRoot =&amp;gt; Parent == null;

        public bool IsLeaf =&amp;gt; Children.Count == 0;

        public int Level =&amp;gt; IsRoot ? 0 : Parent.Level + 1;

        private Tree(T data)
        {
            Children = new LinkedList&amp;lt;ITree&amp;lt;T&amp;gt;&amp;gt;();
            Data = data;
        }

        public static Tree&amp;lt;T&amp;gt; FromLookup(ILookup&amp;lt;T, T&amp;gt; lookup)
        {
            var rootData = lookup.Count == 1 ? lookup.First().Key : default(T);
            var root = new Tree&amp;lt;T&amp;gt;(rootData);
            root.LoadChildren(lookup);
            return root;
        }

        private void LoadChildren(ILookup&amp;lt;T, T&amp;gt; lookup)
        {
            foreach (var data in lookup[Data])
            {
                var child = new Tree&amp;lt;T&amp;gt;(data) {Parent = this};
                Children.Add(child);
                child.LoadChildren(lookup);
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope that helps. Enjoy coding with the &lt;a href="https://medium.com/@dmitry.pavlov"&gt;Coding Machine&lt;/a&gt;…&lt;/p&gt;

</description>
      <category>entityframeworkcore</category>
      <category>extensionmethod</category>
      <category>csharp</category>
      <category>hierarchy</category>
    </item>
    <item>
      <title>How to Add Generated HttpClient to ASP.NET Core Dependency Injection (Right Way)</title>
      <dc:creator>Dmitry Pavlov</dc:creator>
      <pubDate>Sun, 26 May 2019 16:49:58 +0000</pubDate>
      <link>https://dev.to/dr_dimaka/how-to-add-generated-httpclient-to-asp-net-core-dependency-injection-right-way-5731</link>
      <guid>https://dev.to/dr_dimaka/how-to-add-generated-httpclient-to-asp-net-core-dependency-injection-right-way-5731</guid>
      <description>&lt;p&gt;This How-To describes how to inject dependency to HttpClient you generated for PetStore API with &lt;a href="https://marketplace.visualstudio.com/items?itemName=dmitry-pavlov.OpenAPIConnectedService" rel="noopener noreferrer"&gt;OpenAPI (Swagger) Connected Service&lt;/a&gt; to ASP.NET Core application. The sample code is available in &lt;a href="https://github.com/dmitry-pavlov/openapi-connected-service/tree/master/docs/samples/Samples.AspNetCoreMvc.ClientInjectedToStartup" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dmitry-pavlov.OpenAPIConnectedService" rel="noopener noreferrer"&gt;OpenAPI (Swagger) Connected Service&lt;/a&gt; is a Visual Studio extension to generate C# HttpClient code for &lt;a href="https://swagger.io/docs/specification/about/" rel="noopener noreferrer"&gt;OpenAPI (formerly Swagger)&lt;/a&gt; web services with &lt;a href="https://github.com/RSuter/NSwag" rel="noopener noreferrer"&gt;NSwag&lt;/a&gt;. Simply put, it is like kind old &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/additional-tools/wcf-web-service-reference-guide" rel="noopener noreferrer"&gt;Add Service Reference&lt;/a&gt; for WCF or &lt;a href="https://docs.microsoft.com/en-us/sharepoint/dev/general-development/step-2-adding-a-web-reference" rel="noopener noreferrer"&gt;Add Web Reference&lt;/a&gt; for WSDL, but for JSON API we all deal with nowadays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Follow &lt;strong&gt;5 steps&lt;/strong&gt; below to achieve this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gn5ikacw04p2m3ll5j5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gn5ikacw04p2m3ll5j5.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Generate C# HttpClient class for &lt;a href="http://petstore.swagger.io/" rel="noopener noreferrer"&gt;PetStore API&lt;/a&gt; in your ASP.NET Core MVCweb application using &lt;a href="https://marketplace.visualstudio.com/items?itemName=dmitry-pavlov.OpenAPIConnectedService" rel="noopener noreferrer"&gt;OpenAPI (Swagger) Connected Service&lt;/a&gt;. See &lt;a href="https://github.com/dmitry-pavlov/openapi-connected-service/" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt; section to install and run this Visual Studio extension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Add new file PetStoreClient.cs and make sure the class is marked as partial and has the same name and namespace as generated public partial class Client in PetStoreClient.Generated.cs. Also define the interface IPetStoreClient. The idea behind using the interface is to separate the methods you see where your client is used from what you don’t want to expose. In this sample we just expose the method to retrieve the number of pets sold by the store. So we define the method GetSoldPetsCount, which internally uses generated method for &lt;a href="http://petstore.swagger.io/#/pet/findPetsByStatus" rel="noopener noreferrer"&gt;GET pet/findPetsByStatus&lt;/a&gt; endpoint. That is how it might look like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Now let’s use &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests" rel="noopener noreferrer"&gt;HttpClientFactory&lt;/a&gt; to inject the IPetStoreClient. Go to Startup.cs and add this to ConfigureServices method:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; In Index action in HomeController.cs let’s inject IPetStoreClient and pass the number of sold pets to the View:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 5.&lt;/strong&gt; To display the number of sold pets on the default site page add this code to View\Home\Index.cshtml:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That’s it! We have injected generated client for &lt;a href="http://petstore.swagger.io/" rel="noopener noreferrer"&gt;PetStore API&lt;/a&gt; to ASP.NET Core application via the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection" rel="noopener noreferrer"&gt;dependency injection (DI)&lt;/a&gt; software design pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgpbkszuqi863x9k7w1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgpbkszuqi863x9k7w1x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy coding with the &lt;a href="https://medium.com/@dmitry.pavlov" rel="noopener noreferrer"&gt;Coding Machine&lt;/a&gt;…&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>swagger</category>
      <category>dependencyinjection</category>
      <category>codegeneration</category>
    </item>
  </channel>
</rss>
