<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>skalpin.blog</title>
    <description>My personal blog containing posts about technology, science, and programming.
</description>
    <link>http://skalpin.github.io//</link>
    <atom:link href="http://skalpin.github.io//feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 31 Oct 2025 12:53:53 +0000</pubDate>
    <lastBuildDate>Fri, 31 Oct 2025 12:53:53 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>GitHub Universe 2025</title>
        <description>&lt;p&gt;I expected GitHub Universe to be all talks about AI, and AI tools and not very
technical. The talks were hit or miss. Sometimes they were well structured, and
some were all fluff. I was happy to see a few talks that were technical, &lt;em&gt;and&lt;/em&gt;
I was able to attend some talks that were about building developer community. I
really enjoyed the talk by LEGO. The presenter walked through the different
strategies implemented at the company to drive collaboration and product
development.&lt;/p&gt;

&lt;p&gt;The layout of the conference was strange. There isn’t a single conference room.
Instead they booked a &lt;em&gt;campus&lt;/em&gt;. It has several  buildings and sometimes talks
are difficult to get to. They can either be far apart, or I just get lost
getting to it. For example there was a building that has a large conference
room on the north end. However GitHub blocked off a section of the building for
GitHub partners. So to get to the conference room on the north end, I needed to
go outside, and walk around the partner area. Below are some notes from a
couple of the talks I found particularly interesting.&lt;/p&gt;

&lt;h2 id=&quot;developer-experience-at-lego&quot;&gt;Developer Experience at LEGO&lt;/h2&gt;

&lt;p&gt;I particularly enjoyed the talk on building developer experience at LEGO. The
company broke down silos and simplified efforts into products. Product teams
are a cross-functional group that have the people and knowledge necessary to
develop and maintain a product. They split the initiative into 3 main concerns.
Discoverability, Community, and inner-source / documentation.&lt;/p&gt;

&lt;h3 id=&quot;discoverability&quot;&gt;Discoverability&lt;/h3&gt;

&lt;p&gt;Finding the right person to help with a problem is often a friction point for
developers at any large company. It can be difficult to find the right person
to message for any particular problem. It can also be difficult to find
existing packages or APIs you can leverage that already solve your problem. Of
course the tool used is a heavily customized Backstage instance. Backstage is
where you can search for documentation, apis, packages, or other products. Not
only does it make everything discoverable, but it serves as an onboarding tool
for developers new to your product. Communities are also an important
discoverable catalog item in backstage.&lt;/p&gt;

&lt;h3 id=&quot;community&quot;&gt;Community&lt;/h3&gt;

&lt;p&gt;Building community is difficult. To have a community you need to have people
that are driven to work together. It requires people with a shared interest and
energy to thrive. Communities drive newsletters, dev fairs, and an annual
devcon where developers can come listen or speak to their peers about a topic.&lt;/p&gt;

&lt;h3 id=&quot;inner-sourcing-and-documentation&quot;&gt;Inner-sourcing and Documentation&lt;/h3&gt;

&lt;p&gt;Inner-sourcing helps prevent the “Waiting for someone” problem. Often
developers find problems with a dependent package or api that needs to be
correct before the work can continue. Most of the time developers are happy to
contribute to the dependent project to not only lift the block, but also to
contribute back to the larger community of projects using the dependency. For
inner-sourcing to work, each project needs to define contribution guidelines to
facilitate incoming change requests from other developers.&lt;/p&gt;

&lt;h2 id=&quot;codeql&quot;&gt;CodeQL&lt;/h2&gt;

&lt;p&gt;CodeQL is a tool I have been using for some time now, but I wasn’t aware of the
feature that allows for custom extensions. The feature allows for you search
for specific code patterns and alert developers on what was found. The
documentation provided to the developer is included in a markdown file and can
include as much information as necessary to explain why it’s an issue. I am
currently using CodeQL to look for accidental commits with secrets in them, but
I wonder if I can use CodeQL to look for or help teams with migrations. There
will always be documentation that is out of date, and can lead development
teams down the wrong path. With CodeQL I think we can improve the adoption of
newer practices.&lt;/p&gt;
</description>
        <pubDate>Thu, 30 Oct 2025 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2025/10/30/github_universe.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2025/10/30/github_universe.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>DataOps</title>
        <description>&lt;p&gt;I’m new to this world. I’ve been thinking about it recently because
DevOps often get’s questions from Data Science Engieers asking about
how to do certain things in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;, and I’m learning Data Science has some
similarties and differences to traditional software development.&lt;/p&gt;

&lt;h2 id=&quot;software-engineering-vs-data-engineering&quot;&gt;Software Engineering vs Data Engineering&lt;/h2&gt;

&lt;p&gt;In the software world, multiple developers are working on the same
code base. They are all making new features, or correcting issues. Then
when the code is considered “okay”, it runs through a CI/CD pipeline
is packaged together and that package is deployed (or consumed or something).&lt;/p&gt;

&lt;p&gt;In the Data world, multiple engineers are working on the same dataset, but
they’re not really packaging up an artifact to share with the client. The
engineers instead are finding ways to present the data in a meaningful way
for their clients.&lt;/p&gt;

&lt;p&gt;However, there are several process that need to be shared across the data
engineers too. These process will take data from multiple sources, transform
it, and then dump it to a data warehouse, or into another format that is
easier for the engineers to consume.&lt;/p&gt;

&lt;p&gt;Engineers need source control so they can collaborate on pipelines to ETL (or ELT)
data, and to share what they are working on with other engineers. But there’s
no concept of a SQL module that you would package into an artifact for another
engineer to consume. Sharing is purely copy &amp;amp; paste from anothers example.&lt;/p&gt;

&lt;h2 id=&quot;devops&quot;&gt;DevOps&lt;/h2&gt;

&lt;p&gt;DevOps I understand well. Before DevOps, developers would make their changes,
and then tell an operations team how to run the application in production. Operations
engineers were then responsible for making sure the application continued to run. This
works as long as the application works (hint, it never does) and the Operations team
is already setup to handle the workload. For example an application may need a specific
version of the dotnet runtime installed, and the ops team may not have a machine that
supports that yet. You can read all about it yourself in “The Phoenix Project” by Gene Kim
but the answer is that everything works better when developers and operations engineers
work together instead of blaming each other for failing applications.&lt;/p&gt;

&lt;h2 id=&quot;dataops&quot;&gt;DataOps&lt;/h2&gt;

&lt;p&gt;DataOps to me sounds a lot like the Agile manefsto. (&lt;a href=&quot;https://dataopsmanifesto.org/en/&quot;&gt;DataOps&lt;/a&gt; vs &lt;a href=&quot;https://agilemanifesto.org/&quot;&gt;Agile&lt;/a&gt;)
As far as I know, Data Engineers and Operations engineers have never clashed. Data Engineers only need
access to the tools, and data from operations. Also Operations are not responsible for making
sure that a specific query works properly. So why choose the name “DataOps”? I am disappointed.
I was &lt;em&gt;hoping&lt;/em&gt; to find a group of individuals searching for a way to streamline
a Data Engineers workflow. I need something to describe how branches should live in
source control, what the folder structure should look like, and when to use a CI/CD pipeline.
I want &lt;strong&gt;standards&lt;/strong&gt; and &lt;strong&gt;best practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I will be thinking about this more over the next week, but right now I see 2 paths.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Data Engineers use &lt;em&gt;folders&lt;/em&gt; for different environments, and experiments.
Imagine having a dev,qa,prod folder and copying the SQL files from one to the next
when you want to “deploy” to that environment. The source control flow becomes
dead simple. Branch from &lt;em&gt;main&lt;/em&gt;, make your change, merge back to main and destroy
your branch.&lt;/li&gt;
  &lt;li&gt;Data Engineers use git branches for environments, and experiments. This I think
makes sense for experiments. I don’t really want to put it into the master branch
because I don’t know if it works yet. Even if it does work, I don’t know if I want
to keep it. I need this space to be the way I left it so I can revisit it whenever
the business wants to see the results again with new data. Branches for environments
is fine; we’ve been doing that forever. This is where things like ETL processes, and
datawarehouse schema changes should exist because the concerns are shared among the
whole team. Deployments to an environment then are managed by the environment. The database
keeps track of which schema changes have already taken place, and runs the new ones
(in order).&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Fri, 05 Apr 2024 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2024/04/05/Post.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2024/04/05/Post.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Database Concurrency</title>
        <description>&lt;p&gt;I am in a technical book club and we are currently working through a book
“Designing Data-Intesive Applications” by Martin Kleppmann. We just finished
Chapter 7 - Transactions. This chapter focuses on transactions, but really
zeros in on why transactions exist. They exist to help developers prevent
concurrency issues.&lt;/p&gt;

&lt;h2 id=&quot;transactions&quot;&gt;Transactions&lt;/h2&gt;

&lt;p&gt;Personally, transactions are not my first thought when working on an
application feature. Generally I’m concerned with what type of data
needs to be stored, how the applciation should read it, and making
sure the application writes to the correct records. What happens when
multiple users are using the application is often an afterthought. As
in after a bug has been submitted that some data was overwritten.&lt;/p&gt;

&lt;p&gt;Even before committing to using transactions, I prefer to structure the data
in a way that doesn’t require me to update multiple records. I would rather
have my application read and write data in an isolated way so that it never
needs to worry about another user overwriting it.&lt;/p&gt;

&lt;p&gt;Of course this is nieve. Sure, you can structure your data and data access
as cleanly as you want, but you are going to run into situations where
denormalizing the data to improve performance will force you to write
data to multiple records assuming they are in the same state as you read
them.&lt;/p&gt;

&lt;h2 id=&quot;optimistic-concurrency-control&quot;&gt;Optimistic Concurrency Control&lt;/h2&gt;

&lt;p&gt;Optimistic Concurrency Control assumes that data conflicts will not occur
and provides better performance. This is because it does not require
the database to lock and keep track of resources that are being worked on.&lt;/p&gt;

&lt;p&gt;Transictions are one form of optimistic concurrency control, but there
are other ways the application can make sure writes are not ovewriting
another users data.&lt;/p&gt;

&lt;p&gt;There are some great articles that discuss concurrency, but since I tend
to use entity framework with SQL server, this is my favorite.
&lt;a href=&quot;https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations#optimistic-concurrency&quot;&gt;https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations#optimistic-concurrency&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SQL Server has the concept of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rowversion&lt;/code&gt; column type that can be
used by Entity Framework. When data is read / manupliated / written back to the
database, the rowversion remains the same in application code. Then when data is
written back to the database, the database can check the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rowversion&lt;/code&gt; value given
and the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rowversion&lt;/code&gt; on the row. If they don’t match, the database server
can abort the write, and throw an exception to the application code. The application
can then decide what to do with it.&lt;/p&gt;

&lt;h2 id=&quot;aggregate-roots-and-concurrency&quot;&gt;Aggregate Roots and Concurrency&lt;/h2&gt;

&lt;p&gt;So which persistent objects need to have a rowversion column in the relational
database to make sure that data does not get lost? An aggregate is a collection
of objects that make up an entity. For example a Customer entity will have an
address value. But you probably don’t want to access address directly. In our
application Address only makes sense in the context of a Customer. Therefore
our application shouldn’t update an Address directly, it should update a Customer’s
Address.&lt;/p&gt;

&lt;p&gt;Concurrency needs to be considered at the Aggregate Root because the Aggregate Root holds
the invariants to make sure state remains consistent and valid. When the Aggregate
Root object is loaded into memory, it needs to have a concurrency token or
rowversion that will allow the application to detect when the Customer object
has been updated without their knowledge. This will allow the Customer to determine
if it can safely continue with the update, or if it needs to abort the change due
to a conflict.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;This is a quick overview of optimistic concurrency control, transactions, and
how it applies to your application model. I completely skipped over pessimistic
concurrency control because I do not work on any systems that need it, and I don’t
think may do. Most applications can get away with optimistic concurrency control,
but it’s important that application developers think about concurrency. It’s too
easy to do your feature testing locally, find that everything is working okay, and
push changes to quality assurance for testing. Then only to discover bugs that
are difficult to reproduce, diagnose and resolve.&lt;/p&gt;
</description>
        <pubDate>Fri, 29 Mar 2024 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2024/03/29/DatabaseConcurrency.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2024/03/29/DatabaseConcurrency.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Devcontainers</title>
        <description>&lt;p&gt;Development containers have completely changed my local development workflow. They make it easier
for me to use the correct version of the tools I need for each specific project, and they help
keep the tools consistent across my team. So what is a devcontainer?&lt;/p&gt;

&lt;p&gt;The concept of a devcontainer is simple. I want to make changes to an application which means I need
to be able to build and run it locally, however I don’t know what tools I need or how to install them.
In some cases I cannot install the correct version of a tool. This can happen when I am working on
separate projects that need different versions of a tool that cannot be installed at the same time on my
operating system.&lt;/p&gt;

&lt;p&gt;For example, I am writing this blog using Jekyll. I don’t necessarily want to install ruby, gem, and
jekyll on my system to update the blog. It’s much easier to spin up a container with the tools installed
and make the changes in there.&lt;/p&gt;

&lt;p&gt;For this walkthrough I am going to be using Rancher, Visual Studio Code, and the Devcontainer extension.&lt;/p&gt;

&lt;h2 id=&quot;setup-rancher&quot;&gt;Setup Rancher&lt;/h2&gt;

&lt;p&gt;This is the most difficult step getting started with devcontainers. You need to have something to run
the containers, and docker is my tool of choice. Since Docker Desktop is no longer free for Enterprise
developers, I have selected Rancher Desktop to get docker setup on my system. You can download and
install it from &lt;a href=&quot;https://rancherdesktop.io/&quot;&gt;https://rancherdesktop.io/&lt;/a&gt;. You do not need to setup
Kubernetes for this to work properly.&lt;/p&gt;

&lt;h2 id=&quot;setup-visual-studio-code&quot;&gt;Setup Visual Studio Code&lt;/h2&gt;

&lt;p&gt;I’m assuming you already have Visual Studio Code, but just in case yo don’t download and install it from
&lt;a href=&quot;https://code.visualstudio.com/download&quot;&gt;https://code.visualstudio.com/download&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the extensions window, search for “Dev Containers” or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ms-vscode-remote.remote-containers&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;setup-your-project&quot;&gt;Setup your project&lt;/h2&gt;

&lt;p&gt;Open your project folder in Visual Studio Code. From the command window find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dev Containers:Reopen in Container&lt;/code&gt;. This will give you a menu to add the configuration to the user data or to the workspace.
I suggest you choose workspace so that it saves the configuration with your project. That way any
developer who needs to make changes has access to this container.&lt;/p&gt;

&lt;p&gt;Then all you need to do is select the base container image you want to work with. For my blog
I am using Jekyll, so I selected an image with Jekyll installed.&lt;/p&gt;

&lt;h2 id=&quot;edit-your-project-from-a-container&quot;&gt;Edit your project from a container&lt;/h2&gt;

&lt;p&gt;What happes now is the VS Code extension pulls the image, and mounts the folder you had open
into a docker volume and attaches it to the conatiner. It also sets up a non-root user
(probably vscode) in the container so that edits to files are mapped to the appropriate
user on your host system and not root. Additionally it sets up git credentials so you can
make changes and push them to the remote server.&lt;/p&gt;

&lt;p&gt;You’ll notice it created a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.devcontainer&lt;/code&gt; folder with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devcontainer.json&lt;/code&gt; file. This file
tells VSCode that your project can use a devcontainer, and which image to use for it.&lt;/p&gt;

&lt;h2 id=&quot;more-information&quot;&gt;More information&lt;/h2&gt;

&lt;p&gt;For more information checkout &lt;a href=&quot;https://containers.dev/&quot;&gt;https://containers.dev/&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2024/03/15/Devcontainers.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2024/03/15/Devcontainers.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Visio Plugin Testing in Docker</title>
        <description>&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;

&lt;p&gt;I am currently working with a plugin to Visio. We have been writing and running automated tests using the &lt;a href=&quot;https://github.com/microsoft/WinAppDriver&quot;&gt;WinAppDriver&lt;/a&gt;. This driver takes COM endpoints and exposes them as a web service so that your automated tests can be written just like any other website using Selinum. The issue is, when UI tests run locally, they take over the whole work station so you can’t multi task or work on anything else. Additionally I would like to find a way to automate these tests as part of a pipeline so they can be run more frequently.&lt;/p&gt;

&lt;h2 id=&quot;solution-1---setup-a-virtual-machine&quot;&gt;Solution 1 - Setup a virtual machine&lt;/h2&gt;

&lt;p&gt;This works but it feels heavy. I still cannot run tests in parallel. However I can run tests without taking over my main machine which is good because it means I can still respond to emails while the tests run. It would be better if I could get Visio running in a docker container and spin up several instances so I can run tests in parallel.&lt;/p&gt;

&lt;h2 id=&quot;install-visio-in-a-docker-container&quot;&gt;Install Visio in a Docker Container&lt;/h2&gt;

&lt;p&gt;The first hurdle is going to be installing Office, and specifically Visio into a docker container. I got a lot of help from this blog post &lt;a href=&quot;https://medium.com/rkttu/install-microsoft-office-in-windows-container-ce05877138fd&quot;&gt;Install Microsoft Office In Windows Container&lt;/a&gt;. Though I only care about Visio, and we only support the 64 bit version of Visio. I modified the office.xml configuration to look like&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Configuration&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Add&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;OfficeClientEdition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;64&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Channel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Monthly&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Product&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ID=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;VisioProRetail&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;Language&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ID=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en-us&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Product&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Add&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;Updates&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Enabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TRUE&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Channel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Monthly&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;Display&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Level=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;None&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;AcceptEULA=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TRUE&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; 
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;Property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AUTOACTIVATE&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Configuration&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And my docker file looks like&lt;/p&gt;

&lt;div class=&quot;language-docker highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#download odt setup files&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mcr.microsoft.com/windows:1903&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;build&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; C:\\odtsetup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_11617-33601.exe odtsetup.exe&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;odtsetup.exe /quiet /norestart /extract:C:&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;odtsetup

&lt;span class=&quot;c&quot;&gt;#download office files for the selected configuration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mcr.microsoft.com/windows:1903&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;download&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; C:\\odtsetup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; --from=build C:\\odtsetup\\setup.exe .&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; config.xml C:\\config.xml&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;setup.exe /download C:&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;config.xml

&lt;span class=&quot;c&quot;&gt;#copy setup files and run setup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; mcr.microsoft.com/windows:1903&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; C:\\odtsetup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; --from=build C:\\odtsetup\\setup.exe .&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; --from=download C:\\odtsetup\\Office .&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; config.xml C:\\config.xml&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;setup.exe /configure C:&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;config.xml
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#remove odt setup&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rmdir&lt;/span&gt; /s /q C:&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;odtsetup

&lt;span class=&quot;c&quot;&gt;#create a new office object that was installed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;powershell &lt;span class=&quot;nt&quot;&gt;-Command&lt;/span&gt; new-object &lt;span class=&quot;nt&quot;&gt;-comobject&lt;/span&gt; visio.application
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;C:&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;Windows&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;SysWOW64&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;config&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;systemprofile&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;Desktop

&lt;span class=&quot;c&quot;&gt;#activate visio&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;cscript &lt;span class=&quot;s2&quot;&gt;&quot;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\P&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rogram Files&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\M&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;icrosoft Office&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\O&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ffice16&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\O&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SPP.VBS&quot;&lt;/span&gt; /inpkey:&amp;lt;your license key&amp;gt;

&lt;span class=&quot;k&quot;&gt;VOLUME&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; C:\\data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next step will be to install the plugin we are working on, the win app driver, and start a selenium hub node.&lt;/p&gt;

&lt;h2 id=&quot;to-be-continued&quot;&gt;To be continued…&lt;/h2&gt;
</description>
        <pubDate>Tue, 28 Jul 2020 10:50:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2020/07/28/Visio-Plugin-Testing-in-Docker.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2020/07/28/Visio-Plugin-Testing-in-Docker.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Installing nvm in WSL with fish and omf</title>
        <description>&lt;h2 id=&quot;node-versions&quot;&gt;Node Versions&lt;/h2&gt;

&lt;p&gt;Using node on multiple projects is great, until each project starts using a
different version of node &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(╯°□°）╯︵ ┻━┻&lt;/code&gt; Nvm is a tool that allows developers
to manage different versions of node on the same machine. Nvm works great in
Windows, Linux, and OSX; let’s see if we can get it running on the Windows
Subsystem for Linux (WSL). And while we’re at it, let’s get it running with
fish and oh-my-fish (my preferred shell).&lt;/p&gt;

&lt;p&gt;Nvm is a script not a executable. This means an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvm.sh&lt;/code&gt; file is placed on
your computer. To “execute” it, the path to the script is included in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.profile&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; it &lt;strong&gt;(╯°□°）╯︵ ɥsıɟ ʇɹoddus ʇou sǝop&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;installing-nvm&quot;&gt;Installing nvm&lt;/h2&gt;

&lt;h3 id=&quot;step-1-install-nvmsh&quot;&gt;Step 1 Install nvm.sh&lt;/h3&gt;

&lt;p&gt;From &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;the github page&lt;/a&gt; we can start by installing
the script &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-2-install-fenv&quot;&gt;Step 2, Install fenv&lt;/h3&gt;

&lt;p&gt;Next I am going to use the &lt;a href=&quot;https://github.com/oh-my-fish/plugin-foreign-env&quot;&gt;fenv&lt;/a&gt;
to run nvm.sh from bash with all of the appropriate environment variables set.
To install fenv run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;omf install foreign-env&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;step-3-setup-fish-function&quot;&gt;Step 3, Setup fish function&lt;/h3&gt;

&lt;p&gt;The fish shell will allow you to setup aliases just like bash, but it also allows
developers to create functions as modules under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config/fish/functions/&lt;/code&gt;
directory. Create a new file in this directory named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvm.fish&lt;/code&gt;. Copy and paste
the following function into the file&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;nvm
    fenv &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.nvm/nvm.sh &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt; nvm &lt;span class=&quot;nv&quot;&gt;$argv&lt;/span&gt;
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;run-nvm&quot;&gt;Run nvm&lt;/h2&gt;

&lt;p&gt;Now just restart your shell and start using nvm as you normally would!&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Jun 2019 19:23:41 +0000</pubDate>
        <link>http://skalpin.github.io//update/2019/06/21/Installing-nvm-in-WSL-fish.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2019/06/21/Installing-nvm-in-WSL-fish.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Import From Service to SQL</title>
        <description>&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;

&lt;p&gt;why do we need to be talking about this?&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;SQL Server is much faster at loading records in batches.&lt;/li&gt;
  &lt;li&gt;What happens if we need to pull the data from another source? I don’t want to block until the enumerable completes.&lt;/li&gt;
  &lt;li&gt;Migrating data from blob storage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I was recently tasked with moving a large data set of items from Azure blob storage into SQL Server. When I am faced with a migration problem I always look for a producer/consumer solution to keep the memory usage low. Often the dataset is too large to load into memory, and then dump to the destination all at once. I also heavily use IEnumerables because I can return the items that have been retrieved, while the producer goes back to retrieve more.&lt;/p&gt;

&lt;p&gt;Here is example code of how to load items from blob storage. There is a query api, and it will return a set number of records, along with a continuation token if there are more records to retrieve.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RetrieveEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetBlobUrls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;containerRootName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blobFolderName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blob&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadBlobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetBlobUrls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// List the blobs in the container.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BlobContinuationToken&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobContinuationToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobListingDetails&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BlobListingDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetBlobResultSegmentsAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobContinuationToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobListingDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Get the value of the continuation token returned by the listing call.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;blobContinuationToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContinuationToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IListBlobItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blobContinuationToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Loop while the continuation token is not null.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DownloadBlobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;containerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobContainerFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBlobContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;containerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cloudBlockBlob&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CloudBlockBlob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blobUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StreamReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cloudBlockBlob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OpenReadAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadToEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BlobContainerFactory&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobConnectionString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BlobContainerFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobConnectionString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blobConnectionString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobConnectionString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CloudBlobContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetBlobContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;containerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;CloudStorageAccount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TryParse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blobConnectionString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storageAccount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cloudBlobClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storageAccount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateCloudBlobClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cloudBlobClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetContainerReference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;containerName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ExistsAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appinsightsContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assuming you have a large number of JSON files, calling RetrieveEvents will iterate through the blob uri’s in the storage account, download the data, and return it as an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IEnumerable&amp;lt;string&amp;gt;&lt;/code&gt;. So far so good, now let’s try and write those items to SQL.&lt;/p&gt;

&lt;p&gt;SqlBulkCopy is easily the fastest way to move a large number of items to a SQL instance. You can pass it a large number of items, set the batch size, and let SqlBulkCopy batch and upload items for you.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blobContainerFactory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BlobContainerFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;yourconnectionstring&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;WriteAllToSql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RetrieveEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WriteAllToSql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SqlBulkCopy&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SqlBulkCopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connectionString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DestinationTableName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BatchSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EnableStreaming&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;columnMapping&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;columnMappings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ColumnMappings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;columnMapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteToServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataTableAdapter&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataTable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GetDataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataTable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetProperties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Columns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Nullable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetUnderlyingType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PropertyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PropertyType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataRow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;NewRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;dataRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DBNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;dataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataTable&lt;/code&gt; object however, each item in the original enumerable needs to be interated through for a row to be added. The issue is, all of the events need to get loaded into memory before &lt;em&gt;anything&lt;/em&gt; gets written to SQL.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;

&lt;p&gt;Instead of commiting the entire collection at once, let’s add a non-blocking function that creates &lt;em&gt;chunks&lt;/em&gt; of data to be written to SQL. That way the blob storage reader can be waiting on a web request and the SQLBulkCopy can write what it currently has. This extension method will take single items, and create an IEnumerable&amp;lt;IEnumerable&lt;T&gt;&amp;gt; of those items. If there are items in the original collection -&amp;gt; gather them up, otherwise commit what has been gatherd and block until there are more items. This function can optionally take a maximum size if your destination cannot handle a large dataset.&lt;/T&gt;&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnumerableExtensions&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maximumSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BlockingCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConcurrentQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;());&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;producingTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CompleteAdding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsCompleted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetConsumingEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maximumSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HasValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maximumSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;itemList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;producingTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsFaulted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;producingTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using a blocking collection and a Task allows us to iterate through the original list, while still allowing items to be collected and returned. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetConsumingEnumerable()&lt;/code&gt; will block until more items have been added to the queue.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RetrieveEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;WriteAllToSql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, if the calls to blob storage are being throttled, the items will be collected and written to SQL. Also while the first call to SQL is being made, items are still being collected and the initial batch size will increase. It should be noted that SQLBulkCopy will still batch writes to SQL using the batchSize set, so if the items size does grow to 1,000,000 records, SQLBulkCopy will take care of breaking it into chunks itself.&lt;/p&gt;
</description>
        <pubDate>Fri, 15 Feb 2019 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2019/02/15/Import-To-SQL.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2019/02/15/Import-To-SQL.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Dairy Enteligen</title>
        <description>&lt;p&gt;Look! A project I worked on is in the news!
&lt;a href=&quot;http://www.prnewswire.com/news-releases/dairy-farmers-milk-the-power-of-data-to-improve-feed-and-farm-management-practices-with-cargills-dairy-enteligen-300517646.html&quot;&gt;Dairy Enteligen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DahbPaNkZ5M&quot;&gt;Dairy Enteligen Video&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Sep 2017 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2017/09/14/Dairy-Enteligen.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2017/09/14/Dairy-Enteligen.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Use Git to Make Changes</title>
        <description>&lt;p&gt;I have been using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; for a number of years and have come up with a workflow that lets me write code how I want, and then clean up the process later. My philosphy has always been&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Nobody wants to know how I write code. This is a mess!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;creating-a-new-feature&quot;&gt;Creating a new feature&lt;/h2&gt;

&lt;p&gt;Generally on my projects we follow the &lt;em&gt;gitflow&lt;/em&gt; process, but that still leaves me plenty of room to create my own process between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout -b &amp;lt;featureBranch&amp;gt;&lt;/code&gt; to creating a pull request in sourcecontrol. Here’s an overview of my process to introduce changes while I’m working on a team. After selecting a feature to begin work on I’ll create a feature branch. Then I commit a &lt;strong&gt;lot&lt;/strong&gt; and I don’t worry about what my commit messages are. Periodically I’ll check to see if the development branch has been updated and if it has I’ll rebase my changes on top. If my branch has many many commits, I may squash some changes before rebasing onto the develop branch to make conflicts easier to resolve. Then when my feature is complete, I’ll do an interactive rebase onto the develop branch. The rebase allows me to reorder, group, squash, and edit commit messages until each commit is a complete &lt;em&gt;thought&lt;/em&gt; and my history is a few commits ahead of develop. &lt;strong&gt;Then&lt;/strong&gt; I’ll submit a pull request and ask for my branch to be merged into develop. I also use several aliases to make this process easier on myself.&lt;/p&gt;

&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;

&lt;p&gt;First lets start with my tools.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Git for Windows (I’m using windows obviously)&lt;/li&gt;
  &lt;li&gt;Cmder (cmd shell)&lt;/li&gt;
  &lt;li&gt;Poshgit (powershell git tools)&lt;/li&gt;
  &lt;li&gt;Vim&lt;/li&gt;
  &lt;li&gt;kdiff3&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;aliases-used&quot;&gt;Aliases used&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.nf &quot;!f() { git checkout -b stevek/$1; }; f&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.publish &quot;!git push -u origin develop&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.pushf push --force-with-lease&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.f fetch -p&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.lg log --color --graph --pretty=format:&apos;%Cred%h%Creset %s%C(yellow)%d%Creset %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset&apos;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.in &quot;!git lg ..origin/develop&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global alias.update &quot;!git pull --rebase --autostash origin develop&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;have-no-fear&quot;&gt;Have No Fear&lt;/h2&gt;

&lt;p&gt;Git does not delete commits (for something like a month). If you have accidently reset or rebased you can always see the commits you had checked out with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt;. This log keeps track of where you have been and you can always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset --hard &amp;lt;commithash&amp;gt;&lt;/code&gt; to move back to where you were. The only changes you may lose are the ones you didn’t comimit.&lt;/p&gt;

&lt;h2 id=&quot;creating-my-feature-branch&quot;&gt;Creating my feature branch&lt;/h2&gt;

&lt;p&gt;Create your branch with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git nf &amp;lt;itemnumber&amp;gt;-&amp;lt;feature&amp;gt;&lt;/code&gt;. This will create and checkout a branch that looks something like &lt;em&gt;stevek/1122-myNewFeature&lt;/em&gt;. The folder helps me keep track of &lt;strong&gt;my&lt;/strong&gt; branches. Usually I own particular features and work on them myself. Then I generally like to push and set the upstream right away with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git publish&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;making-commits&quot;&gt;Making commits&lt;/h2&gt;

&lt;p&gt;Make commits freely. Do not working about building the code, do not worry about commit messages. This is the reason I love git. While I’m refactoring code I’m making commits that don’t build and half solutions. Then if I need to go back at any point I can find the commit and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset --hard &amp;lt;commithash&amp;gt;&lt;/code&gt;. That will reset my branch back to the specified commit and remove all my changes. Again, the only changes you will lose are the ones you didnt’ commit.&lt;/p&gt;

&lt;h2 id=&quot;watching-for-changes-from-developers&quot;&gt;Watching for Changes From Developers&lt;/h2&gt;

&lt;p&gt;You should fetch the remote repository frequently. I also like to prune at the same time so I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git f&lt;/code&gt;. Then you can check to see if you need to update your feature branch by looking at the incoming commits. Do this with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git in&lt;/code&gt;. Then if there are incoming commits, you can decide what to do. When updating my branch I generally choose to rebase unless I am working with other developers in the branch.&lt;/p&gt;

&lt;h2 id=&quot;cleaning-up-history&quot;&gt;Cleaning Up History&lt;/h2&gt;

&lt;p&gt;Every once in a while I will realize that I’ve made several commits and either merging from develop or rebasing onto develop will probably be difficult. The reason is, you need to resolve conflicts for &lt;strong&gt;each&lt;/strong&gt; commit. Find the commit to rebase onto with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git merge-base &amp;lt;yourbranch&amp;gt; develop&lt;/code&gt;. Then clean up your history with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase -i &amp;lt;mergebasehash&amp;gt;&lt;/code&gt;. You only need to copy the first 6 characters or so of the hash.&lt;/p&gt;

&lt;p&gt;The rebase command will open up your default editor (hopefully vim), and give you instructions on how to correct your commits. Save and close the file. Git will then follow your instructions / break / and open your editor to let you reword the commit messages you wanted to reword.&lt;/p&gt;

&lt;p&gt;During the rebase if you have decided that you messed something up and want to abort run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase --abort&lt;/code&gt;. If instead the rebase worked well and you still want to undo it, take a look at the reflog &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; and choose the previous commit hash. Then execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset --hard &amp;lt;hash&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once complete you will notice that your remote branch and local have gotten out of sync. Execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pushf&lt;/code&gt; to force the remote branch to match your local.&lt;/p&gt;

&lt;h2 id=&quot;grab-changes-from-develop&quot;&gt;Grab Changes From Develop&lt;/h2&gt;

&lt;p&gt;When you feel you are ready to get updates from develop run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git update&lt;/code&gt;. This will rebase your branch against the most recent commit in the remote develop branch and let you make changes to your commits if you wish.&lt;/p&gt;

&lt;p&gt;Again you will have to force your changes to the remote branch with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pushf&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;repeat&quot;&gt;Repeat&lt;/h2&gt;

&lt;p&gt;Continuing on with your work you can repeate the process of rebasing / squashing / updating from develop until you feel the branch is ready and acceptable to be merged into develop.&lt;/p&gt;

&lt;h2 id=&quot;create-a-pull-request&quot;&gt;Create a Pull Request.&lt;/h2&gt;

&lt;p&gt;Each system is a little different, but generally in GitHub or VSTS you would now go find your branch and create a pull request using the web ui. Then your fellow developers will make comments about your code, make you feel like garbage, and eventually accept your request.&lt;/p&gt;

&lt;h2 id=&quot;dont-stop&quot;&gt;Don’t Stop!&lt;/h2&gt;

&lt;p&gt;While this process is happening &lt;strong&gt;You don’t need to wait!&lt;/strong&gt;. Grab another feature or bug, branch from the most recent commit in develop and start working! There is no reason to ever stop working while you are using git. (unless of course there is no work to do)&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Jul 2017 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2017/07/21/Use-Git-to-Make-Changes.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2017/07/21/Use-Git-to-Make-Changes.html</guid>
        
        
        <category>update</category>
        
      </item>
    
      <item>
        <title>Installing Ubuntu on Windows 10</title>
        <description>&lt;h2 id=&quot;get-excited&quot;&gt;Get Excited&lt;/h2&gt;

&lt;p&gt;Because I’m a Windows .NET developer by day and a wannabe Ubuntu developer by night this new
feature in Windows 10 is especially exciting for me so what am I supposed to do besides
write a new blog article about it.&lt;/p&gt;

&lt;h2 id=&quot;windows-10-build-14316&quot;&gt;Windows 10 Build 14316&lt;/h2&gt;

&lt;p&gt;To start with you need to get the Windows 10 Insider Preview build 14316.
The problem is, this cannot just be downloaded and installed. Using your MSDN license
(or whatever) you should be able to find  Windows 10 Insider Preview build 14295.&lt;/p&gt;

&lt;p&gt;Then you need to set yourself up for insider preview builds from Microsoft. To do this
go to Start Menu -&amp;gt; Settings -&amp;gt; Update &amp;amp; security -&amp;gt; Advanced options. From there
you will see instructions on how to setup your account to receive the builds. You also
need to make sure you are setup to receive builds “fast”.&lt;/p&gt;

&lt;p&gt;One more thing to note: I had to wait 24 hours to receive an update to 14316 (bummer).&lt;/p&gt;

&lt;h2 id=&quot;enable-the-linux-feature&quot;&gt;Enable the Linux Feature&lt;/h2&gt;

&lt;p&gt;Good! You’ve now got Windows Insider Preview 14316 installed. No you need to right click on
the start menu and go to “Programs and Features”. Then navigate to “Turn Windows features on or off”.
Once you’re looking at the windows features list select the “Windows Subsystem for Linux (Beta)”.
This feature requires a computer restart.&lt;/p&gt;

&lt;h2 id=&quot;installing-bash&quot;&gt;Installing bash&lt;/h2&gt;

&lt;p&gt;So installing the Linux Subsystem will give you a new program called bash. Run it.
You will be asked if you would like to install bash. Type ‘y’ and hit enter (duh). This will go
download and install what you need to get going with bash. When it’s complete you will be presented
with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root@localhost:~#&lt;/code&gt; prompt. As you probably noticed you’re root… so be careful.&lt;/p&gt;

&lt;h2 id=&quot;updating-bash&quot;&gt;Updating bash&lt;/h2&gt;

&lt;p&gt;The next thing you’ll need to do is update your package list. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get update&lt;/code&gt; will do it, maybe.
I ran into some issues with my network. None of the sources could be found. In fact a simple
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ping www.google.com&lt;/code&gt; didn’t execute successfuly. It turns out there is a minor bug with the bash
and IPv6 so you need to edit your sources list and move the IPv6 ones to the bottom or remove them
completely. My generated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf&lt;/code&gt; looked like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;domain hsd1.mn.comcast.net.
nameserver 2001:558:feed::2
nameserver 2001:558:feed::1
nameserver 192.168.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Open up your favorite editor (vim, emacs, pico) and edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf&lt;/code&gt; to put the IPv6 addresses
at the bottom of the list.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;domain hsd1.mn.comcast.net.
nameserver 192.168.0.1
nameserver 2001:558:feed::2
nameserver 2001:558:feed::1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; you should be able to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get update &amp;amp;&amp;amp; apt-get upgrade&lt;/code&gt; to upgrade your systems package lists.
Unfortunately you might have to do this every time you open bash if you want bash to have access to the internet.&lt;/p&gt;
</description>
        <pubDate>Wed, 13 Apr 2016 00:00:00 +0000</pubDate>
        <link>http://skalpin.github.io//update/2016/04/13/Installing-Ubuntu-on-Windows-10.html</link>
        <guid isPermaLink="true">http://skalpin.github.io//update/2016/04/13/Installing-Ubuntu-on-Windows-10.html</guid>
        
        
        <category>update</category>
        
      </item>
    
  </channel>
</rss>
