<?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: Mohsen Mirshahreza</title>
    <description>The latest articles on DEV Community by Mohsen Mirshahreza (@mirshahreza).</description>
    <link>https://dev.to/mirshahreza</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1871507%2Fe1b7f8ef-affb-4521-987f-4e79fddebc88.png</url>
      <title>DEV Community: Mohsen Mirshahreza</title>
      <link>https://dev.to/mirshahreza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mirshahreza"/>
    <language>en</language>
    <item>
      <title>SequelizeDotNet</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Mon, 03 Aug 2026 12:45:11 +0000</pubDate>
      <link>https://dev.to/mirshahreza/sequelizedotnet-3n6i</link>
      <guid>https://dev.to/mirshahreza/sequelizedotnet-3n6i</guid>
      <description>&lt;p&gt;SequelizeDotNet is simmilar to sequelize for node.js, It is based on schema and is Dabase first.&lt;/p&gt;

</description>
      <category>prisma</category>
      <category>database</category>
      <category>sequelize</category>
      <category>orm</category>
    </item>
    <item>
      <title>معرفی SequelizeDotNet: فلسفه‌ی Database-First سکوئلایز، این‌بار در دات‌نت</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Sat, 01 Aug 2026 12:53:24 +0000</pubDate>
      <link>https://dev.to/mirshahreza/mrfy-sequelizedotnet-flsfhy-database-first-skhwylyz-ynbr-dr-dtnt-289n</link>
      <guid>https://dev.to/mirshahreza/mrfy-sequelizedotnet-flsfhy-database-first-skhwylyz-ynbr-dr-dtnt-289n</guid>
      <description>&lt;p&gt;یک ORM دیتابیس-محور و مبتنی بر DDL صریح برای دات‌نت — Typeهای emit‌شده در runtime، eager loading بدون JOIN، اعلان‌های push مبتنی بر CDC، و تولید GraphQL/OpenAPI مستقیماً از schema.&lt;/p&gt;

&lt;p&gt;اگه با Sequelize.js در دنیای Node.js کار کرده باشید، این حس رو می‌شناسید: اشاره می‌کنید به یک دیتابیس، یک مدل تعریف (یا از روی دیتابیس موجود استخراج) می‌کنید، و در کمتر از چند دقیقه با Model.findAll({ where: {...}, include: [...] }) دارید کوئری می‌زنید. Associationها، hookهای lifecycle، read replica — همه هستن، و همه‌چیز به اندازه‌ی کافی به SQL نزدیک می‌مونه که هیچ‌وقت حس نکنید دارید با یک انتزاع مبارزه می‌کنید.&lt;/p&gt;

&lt;p&gt;داستان اصلی ORM در دات‌نت فرق می‌کنه. Entity Framework Core کتابخانه‌ی فوق‌العاده‌ایه — ولی اساساً code-first کار می‌کنه: شما کلاس‌های DbContext/entity رو تعریف می‌کنید، و migrationها توضیح می‌دن دیتابیس چطور باید تغییر کنه تا با کد شما هماهنگ بشه. این مدل عالیه وقتی اپلیکیشن شما مالک schema است. ولی وقتی دیتابیس از قبل وجود داره، متعلق به یک تیم دیگه (یا حتی یک codebase دیگه، شاید به یک زبان کاملاً متفاوت) است، یا وقتی اصلاً نمی‌خواید کد اپلیکیشن تصمیم بگیره schema چه شکلی باشه، این مدل خیلی خوب جواب نمی‌ده.&lt;/p&gt;

&lt;p&gt;دقیقاً همین خلأ دلیل ساختن SequelizeDotNet بود.&lt;/p&gt;

&lt;p&gt;این کتابخانه واقعاً چیکار می‌کنه&lt;br&gt;
SequelizeDotNet یک ORM با فلسفه‌ی database-first برای دات‌نته، روی شش دیتابیس رابطه‌ای — SQL Server، SQLite، PostgreSQL، MySQL/MariaDB، Oracle، و DB2 — که روی سه تصمیم طراحی غیرقابل‌مذاکره ساخته شده:&lt;/p&gt;

&lt;p&gt;دیتابیس همیشه منبع حقیقته. هیچ‌چیزی از روی یک schema که خودتون نوشتید حدس نمی‌زنه کد شما «باید» چه شکلی باشه. مدل از دیتابیس میاد، نه برعکس.&lt;br&gt;
DDL همیشه صریحه، هیچ‌وقت diff خودکار نیست. تغییرات ساختاری فقط از طریق متدهایی با نام واضح انجام می‌شن — RenameColumnAsync، AddColumnAsync، DropTableAsync — که دولوپر خودش عمداً صداشون می‌زنه. عملیات‌های مخرب نیاز به force: true دارن و در production قفلن مگر اینکه صریحاً override بشن. هیچ چیزی شبیه sync({ alter: true }) سکوئلایز («دیتابیس رو هرجور لازمه با مدلم هماهنگ کن») وجود نداره — چون دقیقاً همین دسته از فیچرهاست که sync خودکار رو در production خطرناک می‌کنه، و حتی مستندات خود سکوئلایز هم به همین دلیل ازش منع می‌کنه.&lt;br&gt;
Typeهای Runtime، نه Code Generation. اینجا دات‌نت کاری می‌کنه که جاوااسکریپت نمی‌تونه: EntityTypeFactory با استفاده از System.Reflection.Emit یک CLR type واقعی به‌ازای هر جدول می‌سازه، که به‌صورت per-table کش می‌شه با تضمین lazy و thread-safe (دقیقاً یک‌بار emit می‌شه، حتی زیر بار concurrent). یک ستون رو در دیتابیس تغییر بدید، همون کوئری بعدی روی اون جدول یک type تازه emit‌شده که این تغییر رو منعکس می‌کنه تحویل می‌ده — بدون rebuild، بدون restart، بدون فایل .cs تولیدشده‌ای که باید sync نگهش دارید.&lt;br&gt;
چند فیچر که خود سکوئلایز نداره&lt;br&gt;
چون سیستم runtime و type دات‌نت اجازه‌ی ساختنشون رو می‌ده:&lt;/p&gt;

&lt;p&gt;Include تودرتو و many-to-many، همیشه بدون JOIN. Include("Author.Publisher.Country") سه لایه‌ی foreign key رو به‌صورت سه کوئری جداگانه، کش‌شده، و فیلترشده با IN (...) طی می‌کنه. IncludeMany("Tags", "dbo", "PostTags", "FK_PostTags_Posts", "FK_PostTags_Tags") همین کار رو از طریق یک جدول واسط صریحاً نام‌گذاری‌شده انجام می‌ده. هیچ‌وقت چیزی پشت یک query plan مبهم و خودکار مخفی نمی‌شه.&lt;br&gt;
مسیریابی Read/Write که واقعاً SQL خام رو هم می‌فهمه. پشتیبانی read replication خود سکوئلایز سابقه‌ی گزارش باگ‌های تکرارشونده داره که کوئری خام بی‌سروصدا از replica pool رد می‌شه. StatementIntentClassifier کلمه‌ی کلیدی ابتدایی کوئری خام رو بررسی می‌کنه دقیقاً برای اینکه همون مسیر میان‌بر هم درست مسیریابی بشه.&lt;br&gt;
Hot-reload بدون restart برای schema. SchemaWatcher پول می‌کنه، مقایسه می‌کنه، و type runtime جدول تغییریافته رو به‌صورت atomic و نسخه‌دار جایگزین می‌کنه — بدون ری‌استارت کردن پروسه.&lt;br&gt;
Change Data Capture سکوئل سرور به‌عنوان یک event قابل‌subscribe. اکثر ORMها هیچ پشتیبانی built-in برای CDC ندارن. CdcChangeWatcher جدول‌های change سکوئل سرور رو به یک event سی‌شارپ تبدیل می‌کنه که یک‌بار subscribe می‌کنید و تمام.&lt;br&gt;
تولید GraphQL و OpenAPI مستقیماً از schema اینتروسپکت‌شده. بدون هیچ مرحله‌ی مدل‌سازی جدا — یک‌بار schema رو بخونید، و یک schema سبک GraphQL یا سند OpenAPI 3.0 مستقیماً از چیزی که دیتابیس از قبل می‌دونه بسازید.&lt;br&gt;
الان دقیقاً کجا ایستاده — صادقانه&lt;br&gt;
این یک پروژه‌ی جوونه (نسخه‌ی ۰.۱.۰) و می‌خوام دقیقاً بگم تا کجا واقعاً تست شده، نه فقط چی پیاده‌سازی شده:&lt;/p&gt;

&lt;p&gt;SQL Server و SQLite به‌طور کامل و زنده تست شدن — بیش از ۱۴۰ تست بین این دو، که هر نوع داده، هر عملگر کوئری، تراکنش‌ها، hookها، schema drift، hot-reload، و bulk insert رو پوشش می‌ده، روی LocalDB واقعی و دیتابیس‌های موقت اجرا شده.&lt;br&gt;
PostgreSQL، MySQL، Oracle، و DB2 کاملاً پیاده‌سازی شدن، پشت همون قرارداد IDialect، ولی فقط در سطح unit-test (query translator) تست شدن — من هنوز نمونه‌ی زنده‌ای از این‌ها ندارم که رفتار end-to-end رو روش تأیید کنم. اگه شما دارید، مشارکت‌تون فوق‌العاده خوش‌اومده — پورت کردن تست‌های زنده‌ی موجود SQL Server/SQLite به یکی از این دیتابیس‌ها با ارزش‌ترین کمکیه که الان می‌شه کرد.&lt;br&gt;
مجموعاً ۲۲۳ تست خودکار، صفر شکست، در این نسخه.&lt;br&gt;
اگه codebase شما از قبل مالک schema خودشه و LINQ چک‌شده در compile-time می‌خواید، احتمالاً EF Core همچنان انتخاب پیش‌فرض بهتریه — بالغ‌تره، توسط مایکروسافت پشتیبانی می‌شه، و اکوسیستم به‌مراتب بزرگ‌تری داره. SequelizeDotNet برای همون سناریوی خاصیه که دیتابیس منبع حقیقته و ترجیح می‌دید همون‌طوری کار کنید که سکوئلایز به یک نسل از دولوپرها یاد داد.&lt;/p&gt;

&lt;p&gt;امتحانش کنید&lt;br&gt;
dotnet add package SequelizeDotNet.Core&lt;br&gt;
dotnet add package SequelizeDotNet.Providers.SqlServer&lt;br&gt;
var engine = new QueryEngine(new SqlServerDialect(), new ModelRegistry());&lt;/p&gt;

&lt;p&gt;var query = QueryEngine.Query("dbo", "Posts")&lt;br&gt;
    .Where("AuthorId", QueryOperator.Equal, 42)&lt;br&gt;
    .Include("FK_Posts_Authors");&lt;/p&gt;

&lt;p&gt;var rows = await engine.ToListAsync(query, connection);&lt;br&gt;
مستندات کامل: Developer Guide · سورس و issueها: github.com/mirshahreza/SequelizeDotNet · لایسنس: MIT.&lt;/p&gt;

&lt;p&gt;تشکر فراوان از همه‌ی کسانی که تا امروز به Sequelize.js کمک کردن — این پروژه به این دلیل وجود داره که اون پروژه بیش از یک دهه ثابت کرد این سبک کار با دیتابیس، در هر زبانی، ارزش داشتنش رو داره.&lt;/p&gt;

&lt;p&gt;اگه تا حالا از یک ابزار migration که اشتباه حدس زده ضربه خوردید، یا دارید یک سرویس دات‌نتی رو نگه‌داری می‌کنید که دیتابیسش مال یک تیم دیگه‌ست، خوشحال می‌شم بازخوردتون رو بشنوم — و اگه یک نمونه‌ی PostgreSQL، MySQL، Oracle یا DB2 دارید که بشه یک test suite رو روش امتحان کرد، حتی بیشتر خوشحال می‌شم.&lt;/p&gt;

&lt;p&gt;SequelizeDotNet · لایسنس MIT · github.com/mirshahreza/SequelizeDotNet&lt;/p&gt;

</description>
      <category>orm</category>
      <category>sequelize</category>
      <category>database</category>
      <category>dynamic</category>
    </item>
    <item>
      <title>Introducing SequelizeDotNet: Bringing Sequelize.js's Database-First Philosophy to .NET</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Fri, 31 Jul 2026 06:13:47 +0000</pubDate>
      <link>https://dev.to/mirshahreza/introducing-sequelizedotnet-bringing-sequelizejss-database-first-philosophy-to-net-3f8i</link>
      <guid>https://dev.to/mirshahreza/introducing-sequelizedotnet-bringing-sequelizejss-database-first-philosophy-to-net-3f8i</guid>
      <description>&lt;p&gt;A database-first, explicit-DDL ORM for .NET — runtime-emitted entity types, JOIN-free eager loading, CDC push notifications, and schema-driven GraphQL/OpenAPI generation.&lt;/p&gt;

&lt;p&gt;If you've built anything with Sequelize.js in the Node.js world, you know the feeling: point it at a database, define (or reverse-engineer) a model, and you're querying with Model.findAll({ where: {...}, include: [...] }) within minutes. Associations, lifecycle hooks, read replicas — it's all there, and it stays close enough to SQL that you never feel like you're fighting an abstraction.&lt;/p&gt;

&lt;p&gt;.NET's dominant ORM story is different. Entity Framework Core is excellent — but it's fundamentally code-first: you declare DbContext/entity classes, and migrations describe how the database should change to match your code. That's a great model when your application owns the schema. It's a much worse fit when the database already exists, is owned by another team (or another codebase, possibly in another language entirely), or when you simply don't want application code deciding what the schema should look like.&lt;/p&gt;

&lt;p&gt;That gap is why I built SequelizeDotNet.&lt;/p&gt;

&lt;p&gt;What it actually does&lt;br&gt;
SequelizeDotNet is a database-first ORM for .NET across six relational databases — SQL Server, SQLite, PostgreSQL, MySQL/MariaDB, Oracle, and DB2 — built on three non-negotiable design decisions:&lt;/p&gt;

&lt;p&gt;The database is the source of truth, always. Nothing infers what your code "should" look like from a schema you wrote. The model comes from the database.&lt;br&gt;
Explicit DDL, never automatic diffing. Structural changes happen through clearly-named method calls — RenameColumnAsync, AddColumnAsync, DropTableAsync — that a developer invokes deliberately. Destructive operations require force: true and are locked in production unless explicitly overridden. There's no sync({ alter: true })-style "make the database match my model, however that requires" — because that's exactly the class of feature that makes automatic schema sync dangerous in production, and Sequelize's own docs discourage it for good reason.&lt;br&gt;
Runtime types, not code generation. Here's where .NET gets to do something JavaScript can't: EntityTypeFactory emits a real CLR type per table via System.Reflection.Emit, cached per-table with a lazy, thread-safe, single-emission guarantee. Change a column in the database, and the next query against that table gets a freshly emitted type reflecting it — no rebuild, no restart, no generated .cs file to keep in sync.&lt;br&gt;
A few things I got to build that Sequelize itself doesn't have&lt;br&gt;
Because .NET's runtime and type system make them possible:&lt;/p&gt;

&lt;p&gt;Nested and many-to-many eager loading, always JOIN-free. Include("Author.Publisher.Country") walks three foreign-key hops as three separate, cached, IN (...)-filtered queries. IncludeMany("Tags", "dbo", "PostTags", "FK_PostTags_Posts", "FK_PostTags_Tags") does the same through an explicitly-named junction table. Nothing is ever hidden behind an opaque generated JOIN plan.&lt;br&gt;
Read/write routing that actually understands raw SQL. Sequelize's read replication support has had recurring reports of raw queries silently bypassing the replica pool. StatementIntentClassifier inspects a raw query's leading keyword specifically so that escape hatch stays correctly routed too.&lt;br&gt;
Zero-restart schema hot-reload. SchemaWatcher polls, diffs, and swaps the runtime entity type for a changed table — atomically, versioned — without restarting the process.&lt;br&gt;
SQL Server Change Data Capture as a subscribable event. Most ORMs have zero built-in CDC consumption. CdcChangeWatcher turns SQL Server's CDC change tables into a C# event you subscribe to once.&lt;br&gt;
GraphQL and OpenAPI generation straight from the introspected schema. No separate modeling step — introspect once, generate a GraphQL SDL schema or an OpenAPI 3.0 document from what the database already knows.&lt;br&gt;
Where it stands today — honestly&lt;br&gt;
This is a young project (v0.1.0) and I want to be upfront about exactly how far it's been verified, not just what's implemented:&lt;/p&gt;

&lt;p&gt;SQL Server and SQLite are exhaustively live-tested — 140+ tests between them, covering every data type, every query operator, transactions, hooks, schema drift, hot-reload, and bulk insert, run against real LocalDB and temp-file databases.&lt;br&gt;
PostgreSQL, MySQL, Oracle, and DB2 are fully implemented behind the exact same IDialect contract, but only unit-tested at the query-translator level — I don't have live instances of these to verify end-to-end behavior against yet. If you do, contributions are very welcome — porting the existing SQL Server/SQLite live test suites to one of these engines is the single most valuable thing anyone could contribute right now.&lt;br&gt;
223 automated tests total, 0 failures, as of this release.&lt;br&gt;
If your codebase already owns its schema and you want compile-time-checked LINQ, EF Core is very likely still the better default choice today — it's mature, Microsoft-backed, and has a much larger ecosystem. SequelizeDotNet is for the specific case where the database is the source of truth and you'd rather work the way Sequelize taught a generation of developers to work.&lt;/p&gt;

&lt;p&gt;Try it&lt;br&gt;
dotnet add package SequelizeDotNet.Core&lt;br&gt;
dotnet add package SequelizeDotNet.Providers.SqlServer&lt;br&gt;
var engine = new QueryEngine(new SqlServerDialect(), new ModelRegistry());&lt;/p&gt;

&lt;p&gt;var query = QueryEngine.Query("dbo", "Posts")&lt;br&gt;
    .Where("AuthorId", QueryOperator.Equal, 42)&lt;br&gt;
    .Include("FK_Posts_Authors");&lt;/p&gt;

&lt;p&gt;var rows = await engine.ToListAsync(query, connection);&lt;br&gt;
Full docs: Developer Guide · Source &amp;amp; issues: github.com/mirshahreza/SequelizeDotNet · License: MIT.&lt;/p&gt;

&lt;p&gt;Huge thanks to everyone who's ever contributed to Sequelize.js — this project exists because that one spent over a decade proving this way of working with databases is worth having, in any language.&lt;/p&gt;

&lt;p&gt;If you've been burned by a migration tool guessing wrong, or you're maintaining a .NET service against a database another team owns, I'd love your feedback — and if you have a PostgreSQL, MySQL, Oracle, or DB2 instance you can point a test suite at, I'd love that even more.&lt;/p&gt;

&lt;p&gt;SequelizeDotNet · MIT License · github.com/mirshahreza/SequelizeDotNet&lt;/p&gt;

</description>
      <category>sequelize</category>
      <category>orm</category>
      <category>prisma</category>
      <category>database</category>
    </item>
    <item>
      <title>Dynamic React: Rendering Remote JSX without a Build Step</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Tue, 18 Nov 2025 22:03:51 +0000</pubDate>
      <link>https://dev.to/mirshahreza/dynamic-react-rendering-remote-jsx-without-a-build-step-2aal</link>
      <guid>https://dev.to/mirshahreza/dynamic-react-rendering-remote-jsx-without-a-build-step-2aal</guid>
      <description>&lt;h2&gt;
  
  
  Dynamic React: Rendering Remote JSX without a Build Step
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Modern React development is often synonymous with complex build pipelines involving Webpack, Vite, or Rollup. While these tools offer optimization, they introduce a significant barrier to entry and rigidity. This project, &lt;strong&gt;ReactDynaCodeDynaHtml&lt;/strong&gt;, demonstrates a powerful alternative: loading, compiling, and rendering React components dynamically in the browser at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. In-Browser Compilation with Babel Standalone
&lt;/h3&gt;

&lt;p&gt;Instead of pre-compiling JSX, this project utilizes &lt;code&gt;babel.min.js&lt;/code&gt; (Babel Standalone). This library runs entirely in the browser, transforming JSX syntax into standard JavaScript that the browser can execute on the fly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Dynamic Fetching
&lt;/h3&gt;

&lt;p&gt;The application uses the standard &lt;code&gt;fetch&lt;/code&gt; API to retrieve component code (stored in &lt;code&gt;.html&lt;/code&gt; or &lt;code&gt;.js&lt;/code&gt; files) as plain text strings. This allows components to be stored remotely or locally and loaded only when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Scoped Execution via &lt;code&gt;new Function&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The heart of the system is the &lt;code&gt;DynamicContent&lt;/code&gt; loader. Once the code is fetched and transformed by Babel, it is executed using the &lt;code&gt;new Function&lt;/code&gt; constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;contextKeys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;funcBody&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inject dependencies (like &lt;code&gt;React&lt;/code&gt;) explicitly.&lt;/li&gt;
&lt;li&gt;Pass props and context variables dynamically.&lt;/li&gt;
&lt;li&gt;Isolate the component's scope to prevent global namespace pollution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Build Configuration&lt;/strong&gt;: No &lt;code&gt;npm run build&lt;/code&gt;, no &lt;code&gt;node_modules&lt;/code&gt; hell, and no complex config files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot-Swappable Architecture&lt;/strong&gt;: You can update a component file on the server, and clients will see the change immediately upon refresh without redeploying the entire application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime Flexibility&lt;/strong&gt;: Ideal for CMS-like structures where layout or logic needs to be defined by the backend or changed frequently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rapid Prototyping&lt;/strong&gt;: Excellent for quick experiments or adding React to legacy applications without a full rewrite.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Use
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setup&lt;/strong&gt;: Ensure &lt;code&gt;index.html&lt;/code&gt; includes React, ReactDOM, and Babel Standalone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Loader&lt;/strong&gt;: Use the &lt;code&gt;DynamicContent&lt;/code&gt; component to load external files.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DynamicContent&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"./my-component.js"&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Component Files&lt;/strong&gt;: Write standard React functional components in your external files. They should return the JSX element directly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While not a replacement for build steps in massive, performance-critical applications, this "No-Build" approach offers unmatched flexibility for dynamic content, plugin systems, and lightweight integrations.&lt;/p&gt;

&lt;p&gt;Source Code&lt;br&gt;
You can find the complete source code for this project on GitHub: &lt;a href="https://github.com/mirshahreza/ReactDynaCodeDynaHtml" rel="noopener noreferrer"&gt;https://github.com/mirshahreza/ReactDynaCodeDynaHtml&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>buildless</category>
      <category>dynamic</category>
    </item>
    <item>
      <title>Geographic in Zync: PostGIS-Inspired Spatial Utilities for SQL Server</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Wed, 29 Oct 2025 04:42:01 +0000</pubDate>
      <link>https://dev.to/mirshahreza/geographic-in-zync-postgis-inspired-spatial-utilities-for-sql-server-25gf</link>
      <guid>https://dev.to/mirshahreza/geographic-in-zync-postgis-inspired-spatial-utilities-for-sql-server-25gf</guid>
      <description>&lt;h1&gt;
  
  
  Geographic in Zync: PostGIS-Inspired Spatial Utilities for SQL Server
&lt;/h1&gt;

&lt;p&gt;Zync is a lightweight, Git-powered package manager for SQL Server that turns collections of SQL scripts into installable, dependency-aware packages. It helps teams ship consistent, reusable database utilities with simple, discoverable commands.&lt;/p&gt;

&lt;p&gt;This article focuses on the Geographic package and how it intentionally mirrors PostGIS patterns from PostgreSQL—so spatial developers can feel at home while working on Microsoft SQL Server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/mirshahreza/Zync" rel="noopener noreferrer"&gt;https://github.com/mirshahreza/Zync&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Geographic package folder: MsSql/Packages/Geographic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why PostGIS patterns?
&lt;/h2&gt;

&lt;p&gt;PostGIS is the de facto standard for spatial data processing in PostgreSQL. Its thoughtful API design, consistent naming (ST_*), and rich function set have shaped how many engineers think about geospatial work.&lt;/p&gt;

&lt;p&gt;The Zync Geographic package adopts the same mental model and naming conventions so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function names and semantics are familiar to PostGIS users.&lt;/li&gt;
&lt;li&gt;Common tasks (constructing geometry, spatial relationships, buffering, distance queries) look and feel similar.&lt;/li&gt;
&lt;li&gt;Migration between PostgreSQL/PostGIS and SQL Server is easier for mixed environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under the hood, these functions are implemented using SQL Server's native spatial types (geometry and geography) and T‑SQL, and they expose a PostGIS-like surface area where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design highlights
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ST_* naming: All spatial helpers follow the ST_* convention with a protective Zz prefix, e.g., ZzST_Buffer, ZzST_Contains, ZzST_DWithin.&lt;/li&gt;
&lt;li&gt;Geometry-first: Core ST_* functions operate on SQL Server geometry; where geodetic accuracy is needed, separate helpers use latitude/longitude and the Haversine formula.&lt;/li&gt;
&lt;li&gt;WKT/WKB friendly: Constructors and I/O helpers accept and return WKT/WKB, easing copy/paste and testing.&lt;/li&gt;
&lt;li&gt;SRID defaults: SRID 4326 (WGS 84) is the default when an SRID is not explicitly provided.&lt;/li&gt;
&lt;li&gt;Familiar semantics: Names and behavior are intentionally aligned with the PostGIS reference where supported by SQL Server's spatial stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the quick reference: MsSql/Doc/POSTGIS_FUNCTIONALITIES.md&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s included
&lt;/h2&gt;

&lt;p&gt;Beyond utility routines like coordinate validation and distance conversions, the package ships 45+ PostGIS‑style functions (ZzST_*) including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Geometry constructors: ZzST_Point, ZzST_MakePoint, ZzST_MakeLine, ZzST_MakePolygon, ZzST_MakeEnvelope&lt;/li&gt;
&lt;li&gt;I/O helpers: ZzST_AsText, ZzST_AsBinary, ZzST_GeomFromText, ZzST_GeomFromWKB&lt;/li&gt;
&lt;li&gt;Accessors: ZzST_X, ZzST_Y, ZzST_GeometryType, ZzST_SRID&lt;/li&gt;
&lt;li&gt;Measurements and predicates: ZzST_Distance, ZzST_Length, ZzST_Area, ZzST_Perimeter, ZzST_Contains, ZzST_Within, ZzST_Intersects, ZzST_DWithin&lt;/li&gt;
&lt;li&gt;Processing: ZzST_Buffer, ZzST_Centroid, ZzST_Envelope, ZzST_ConvexHull, ZzST_PointOnSurface&lt;/li&gt;
&lt;li&gt;Set operations: ZzST_Union, ZzST_Intersection, ZzST_Difference, ZzST_SymDifference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll also find pragmatic helpers commonly needed in app backends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ZzIsPointInRadius, ZzGetPointsInRadius, ZzGetBoundingBox, ZzGetNearestPoint&lt;/li&gt;
&lt;li&gt;Converters and formatters: ZzConvertDMSToDecimal, ZzConvertDecimalToDMS, ZzConvertDistance/Area/Speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browse the full list and examples in MsSql/Packages/Geographic/README.md&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage examples
&lt;/h2&gt;

&lt;p&gt;Note: geometry is used below; replace with geography where your use case requires spheroid-aware measurements. Default SRID is 4326 unless specified.&lt;/p&gt;

&lt;p&gt;1) Construct points and lines (PostGIS‑like):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- POINT(lon lat)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_AsText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_MakePoint&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3890&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6892&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;WKT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- LINESTRING from two points&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_AsText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_MakeLine&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s1"&gt;'51.3890,35.6892;51.4000,35.7000'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;WKT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Spatial relationships and predicates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Envelope (bbox) that contains a point&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bbox&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_MakeEnvelope&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;   &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_GeomFromText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s1"&gt;'POINT(51.3890 35.6892)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_Contains&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;bbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ContainsPoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- 1 = true, 0 = false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Distance and proximity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Are two points within 1km?&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_GeomFromText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s1"&gt;'POINT(51.3890 35.6892)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_GeomFromText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s1"&gt;'POINT(51.4000 35.7000)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_DWithin&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;IsNearby&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Buffering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create a small buffer around a point (~units depend on SRID)&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_GeomFromText&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s1"&gt;'POINT(51.3890 35.6892)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4326&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_AsText&lt;/span&gt;&lt;span class="p"&gt;]([&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzST_Buffer&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;Buffered&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) “App friendly” helpers with lat/lon inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Check if a point (lat/lon) is within a radius (KM/MILE/M)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ZzIsPointInRadius&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6892&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3890&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'KM'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;InRadius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Find points within a radius around a center point (example table schema assumed)&lt;/span&gt;
&lt;span class="c1"&gt;-- SELECT * FROM [dbo].[ZzGetPointsInRadius](&lt;/span&gt;
&lt;span class="c1"&gt;--   @centerLat, @centerLon, @radiusValue, @radiusUnit, @YourPointsTable&lt;/span&gt;
&lt;span class="c1"&gt;-- );&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mapping for PostGIS users
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ST_* naming is preserved with a Zz prefix: e.g., PostGIS ST_Buffer ≈ ZzST_Buffer.&lt;/li&gt;
&lt;li&gt;WKT/WKB inputs are supported via ZzST_GeomFromText and ZzST_GeomFromWKB.&lt;/li&gt;
&lt;li&gt;SRID management via ZzST_SRID and ZzST_SetSRID (no transform).&lt;/li&gt;
&lt;li&gt;SQL Server equivalents (internal) may differ in name (e.g., STBuffer, STDistance), but the wrapper functions provide PostGIS‑like ergonomics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick mapping table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PostGIS&lt;/th&gt;
&lt;th&gt;Zync Geographic&lt;/th&gt;
&lt;th&gt;Notes/Differences&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ST_Buffer&lt;/td&gt;
&lt;td&gt;ZzST_Buffer&lt;/td&gt;
&lt;td&gt;Buffers on geometry; units depend on the SRID.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_DWithin&lt;/td&gt;
&lt;td&gt;ZzST_DWithin&lt;/td&gt;
&lt;td&gt;Proximity within a distance (units = coordinate system units). Consider geography for geodetic accuracy over long distances.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_Intersects&lt;/td&gt;
&lt;td&gt;ZzST_Intersects&lt;/td&gt;
&lt;td&gt;Returns 0/1; works across geometry types.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_Contains&lt;/td&gt;
&lt;td&gt;ZzST_Contains&lt;/td&gt;
&lt;td&gt;Tests if A completely contains B.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_Within&lt;/td&gt;
&lt;td&gt;ZzST_Within&lt;/td&gt;
&lt;td&gt;Tests if A is within B.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_Distance&lt;/td&gt;
&lt;td&gt;ZzST_Distance&lt;/td&gt;
&lt;td&gt;Minimum 2D distance; for lat/lon geodetic cases use ZzCalculateDistance (Haversine).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_AsText&lt;/td&gt;
&lt;td&gt;ZzST_AsText&lt;/td&gt;
&lt;td&gt;WKT output for viewing/debugging.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ST_GeomFromText&lt;/td&gt;
&lt;td&gt;ZzST_GeomFromText&lt;/td&gt;
&lt;td&gt;Construct geometry from WKT with SRID.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Caveats and tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be explicit about SRIDs when mixing data from multiple sources.&lt;/li&gt;
&lt;li&gt;Geography vs geometry: choose geography for long‑distance geodetic calculations; use geometry for planar operations and most predicates.&lt;/li&gt;
&lt;li&gt;Tolerance and units: buffer radii and distances depend on the coordinate system—prefer consistent SRIDs (WGS 84 for GPS).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Install directly from the Zync repository using the Zync command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Install the entire Geographic package&lt;/span&gt;
&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Zync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s1"&gt;'i Geographic'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Or install only spatial functions&lt;/span&gt;
&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Zync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s1"&gt;'i Geographic/ZzST_*.sql'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't have Zync yet, run MsSql/Zync.sql from the repository to bootstrap the core procedure. See MsSql/Doc/ARTICLE_EN.md for a gentle introduction and MsSql/scripts/README.md for automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Zync repository: &lt;a href="https://github.com/mirshahreza/Zync" rel="noopener noreferrer"&gt;https://github.com/mirshahreza/Zync&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PostGIS docs: &lt;a href="https://postgis.net/docs/" rel="noopener noreferrer"&gt;https://postgis.net/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SQL Server spatial types: geometry and geography&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you’ve been productive with PostGIS, you’ll feel right at home: the Zync Geographic package brings a familiar, modern spatial toolbox to SQL Server—tested, documented, and ready for production.&lt;/p&gt;

</description>
      <category>database</category>
      <category>gis</category>
      <category>sqlserver</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Stop Juggling SQL Scripts: Introducing Zync, the Database Package Manager</title>
      <dc:creator>Mohsen Mirshahreza</dc:creator>
      <pubDate>Fri, 26 Sep 2025 21:24:36 +0000</pubDate>
      <link>https://dev.to/mirshahreza/stop-juggling-sql-scripts-introducing-zync-the-database-package-manager-54bk</link>
      <guid>https://dev.to/mirshahreza/stop-juggling-sql-scripts-introducing-zync-the-database-package-manager-54bk</guid>
      <description>&lt;p&gt;If you’ve ever worked on a large database project, you know the pain. You have folders filled with SQL scripts for stored procedures, functions, and views. Script &lt;code&gt;A&lt;/code&gt; depends on &lt;code&gt;B&lt;/code&gt;, which depends on &lt;code&gt;C&lt;/code&gt;. Deploying to a new environment means running them in the correct order, and heaven forbid you miss one. Sharing reusable utilities across projects is a copy-paste nightmare.&lt;/p&gt;

&lt;p&gt;We’ve built powerful package managers for our application code—npm for Node.js, NuGet for .NET, Pip for Python. They handle dependencies, versioning, and distribution flawlessly. So why are we still managing database scripts like it’s 1999?&lt;/p&gt;

&lt;p&gt;It’s time for a change. Introducing &lt;strong&gt;Zync&lt;/strong&gt;, a simple but powerful package manager for SQL Server, designed to bring the convenience of modern package management directly into your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Chaos of Manual Script Management
&lt;/h3&gt;

&lt;p&gt;Before we dive into the solution, let’s appreciate the problem. Traditionally, managing a collection of database objects involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Manual Dependency Tracking:&lt;/strong&gt; You have to remember that &lt;code&gt;CreateUserView.sql&lt;/code&gt; must run after &lt;code&gt;CreateUserTable.sql&lt;/code&gt;. This knowledge is often stored in a developer's head or a fragile &lt;code&gt;README&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Scattered Scripts:&lt;/strong&gt; Utility functions and procedures are often scattered across different project folders, leading to code duplication and maintenance headaches.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inconsistent Deployment:&lt;/strong&gt; Deploying to a new database is often a manual, error-prone process that can easily lead to inconsistencies between development, staging, and production environments.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficult Collaboration:&lt;/strong&gt; Sharing a set of useful database tools with your team or the community is far from straightforward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zync was born out of this frustration. It treats your database objects as what they are: &lt;strong&gt;packages&lt;/strong&gt;—modular, reusable, and dependency-aware units of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Zync Simplifies Your Workflow
&lt;/h3&gt;

&lt;p&gt;Zync is built around a single stored procedure, &lt;code&gt;dbo.Zync&lt;/code&gt;, that acts as your command-line interface inside SQL Server Management Studio (SSMS). Once installed, it gives you access to a world of functionality through simple commands.&lt;/p&gt;

&lt;p&gt;The core philosophy is simple: host your SQL packages in a GitHub repository, and let Zync handle the rest.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Concepts:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;📦 Package Management:&lt;/strong&gt; Group related SQL objects (procedures, functions, etc.) into a "package," which is simply a folder in a repository.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🔄 Automatic Dependency Resolution:&lt;/strong&gt; Define dependencies for a package, and Zync will automatically fetch and install them first.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🎯 Simple Commands:&lt;/strong&gt; A clean, intuitive command structure for listing and installing packages.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🏗️ Standardized Repositories:&lt;/strong&gt; Use the official Zync repository or point it to your own for private packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting Started with Zync
&lt;/h3&gt;

&lt;p&gt;Ready to give it a try? It only takes a few minutes to get up and running.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Install the Zync Stored Procedure
&lt;/h4&gt;

&lt;p&gt;First, you need to install the core &lt;code&gt;Zync&lt;/code&gt; procedure in your target database. Just download and run the &lt;a href="https://github.com/mirshahreza/Zync/blob/main/MsSql/Zync.sql" rel="noopener noreferrer"&gt;&lt;code&gt;Zync.sql&lt;/code&gt;&lt;/a&gt; script from the official repository. This one-time setup is all you need.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: List Available Packages
&lt;/h4&gt;

&lt;p&gt;Once installed, you can see which packages are available in the default repository with the &lt;code&gt;ls&lt;/code&gt; (list) command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Zync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s1"&gt;'ls'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command queries the GitHub API and returns a list of available packages (directories) you can install.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fetching available packages from repository...
Available packages:
-------------------
AppEnd
DbUtils
Number
String
-------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Install Your First Package
&lt;/h4&gt;

&lt;p&gt;Let's say you need a set of string manipulation utilities. You can install the &lt;code&gt;String&lt;/code&gt; package with the &lt;code&gt;i&lt;/code&gt; (install) command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Zync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s1"&gt;'i String'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what happens behind the scenes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Zync constructs the URL to the package's main SQL file in the repository.&lt;/li&gt;
&lt;li&gt; It fetches the content of the script.&lt;/li&gt;
&lt;li&gt; It checks for any dependencies listed at the top of the file and installs them first.&lt;/li&gt;
&lt;li&gt; Finally, it executes the script, creating all the objects from the &lt;code&gt;String&lt;/code&gt; package in your database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Installing package: 'String'...
 -&amp;gt; Fetched 'String' successfully.
 -&amp;gt; Package 'String' installed successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like that, you now have access to useful functions like &lt;code&gt;ZzSplitString&lt;/code&gt; and &lt;code&gt;ZzCountWord&lt;/code&gt; without ever leaving your query editor.&lt;/p&gt;

&lt;p&gt;You can also install a single script from a package if you don't need the entire collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Installs only the ZzSplitString function&lt;/span&gt;
&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Zync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s1"&gt;'i String/ZzSplitString.sql'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Glimpse into the Zync Ecosystem
&lt;/h3&gt;

&lt;p&gt;The default repository already includes several useful packages to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;DbUtils:&lt;/strong&gt; A powerful suite of tools for database administration, including procedures to create/drop tables, manage columns, and analyze object dependencies.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;String:&lt;/strong&gt; A collection of functions for common string operations like splitting, trimming, and counting.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Number:&lt;/strong&gt; Helper functions for formatting numbers and converting byte sizes (e.g., to KB, MB, GB).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AppEnd:&lt;/strong&gt; A set of building blocks for applications, including user and role management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Future is Bright
&lt;/h3&gt;

&lt;p&gt;Zync is just getting started. The vision is to create a rich ecosystem of reusable database components. The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Support for other databases&lt;/strong&gt; like PostgreSQL, MySQL, and Oracle.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Package versioning&lt;/strong&gt; to manage different versions of a package.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;An &lt;code&gt;uninstall&lt;/code&gt; command&lt;/strong&gt; to safely remove packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Join the Movement
&lt;/h3&gt;

&lt;p&gt;Managing database code shouldn't be a chore. Zync offers a streamlined, modern approach that saves time and reduces errors. It empowers developers to build, share, and reuse database utilities with ease.&lt;/p&gt;

&lt;p&gt;Check out the project on GitHub, give it a star, and try it out in your own projects. Contributions, feedback, and ideas are always welcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find the project here: &lt;a href="https://github.com/mirshahreza/Zync" rel="noopener noreferrer"&gt;https://github.com/mirshahreza/Zync&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Mohsen Mirshahreza&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>tooling</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
