Havit.Business 2.1.0

Prefix Reserved
dotnet add package Havit.Business --version 2.1.0
                    
NuGet\Install-Package Havit.Business -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Havit.Business" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Havit.Business" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Havit.Business" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Havit.Business --version 2.1.0
                    
#r "nuget: Havit.Business, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Havit.Business@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Havit.Business&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Havit.Business&version=2.1.0
                    
Install as a Cake Tool

HAVIT .NET Framework Extensions - Business Class Library

Migrace na verzi 2.1.0

Verze 2.1.0 (Havit.Business, Havit.Data, Havit.Business.BLGenerator) přechází z System.Data.SqlClient na Microsoft.Data.SqlClient (7.1.1). System.Data.SqlClient je u .NET Frameworku součástí frameworku a už se dál nevyvíjí, Microsoft.Data.SqlClient je jeho nástupce.

Jde o breaking change. Typy SqlConnection, SqlCommand, SqlParameter, SqlException, SqlDataReader, SqlDataRecord... z obou knihoven jsou navzájem nekompatibilní, proto je potřeba přejít na novou knihovnu celým kódem najednou. Smíchání typů obou knihoven se projeví až za běhu (typicky InvalidCastException), ne při kompilaci.

Co je potřeba udělat

  1. Aktualizovat balíčky Havit.Business a Havit.Business.BLGenerator na 2.1.x (a případně Havit.Data, pokud ho referencujete přímo).
  2. Odebrat případné vlastní reference na System.Data.SqlClient.
  3. Přegenerovat business vrstvu aktualizovaným BL Generatorem.
  4. Ručně upravit negenerovaný kód (soubory Entita.cs a EntitaCollection.cs si generátor při přegenerování opraví sám, viz níže).
  5. Zkontrolovat connection stringy (výchozí Encrypt=True) a konfiguraci.
  6. Zkompilovat a spustit testy.

1. Závislosti

  • Aktualizujte Havit.Business na 2.1.0. Přes Havit.Data 2.1.0 přinese tranzitivně Microsoft.Data.SqlClient 7.1.1.
  • Odeberte z projektů závislost na NuGet balíčku System.Data.SqlClient, pokud ji máte (na .NET Frameworku není pro System.Data.SqlClient balíček potřeba, je ve frameworku).
  • Pokud máte vlastní reference na Microsoft.Data.SqlClient, sjednoťte verzi (nejméně 7.1.1) nebo je odeberte a spolehněte se na tranzitivní závislost.
  • Nainstalujte balíček Havit.Business.BLGenerator ve verzi 2.1.0 (generátor ze starší verze generuje kód pro System.Data.SqlClient).

2. Existující generovaný kód: přegenerovat BL Generatorem

Ano, business vrstvu přegenerujte aktualizovaným BL Generatorem (2.1.0), stejným způsobem jako dosud.

Změny ve vygenerovaném kódu:

  • v souborech se používá using Microsoft.Data.SqlClient; místo using System.Data.SqlClient; (všechny soubory _generated; v existujících souborech Entita.cs a EntitaCollection.cs generátor jen tento řádek vymění, viz níže);
  • generátor už negeneruje přepis Sort(string propertyName, bool ascending) v *CollectionBase (metoda byla [Obsolete] a v BusinessObjectCollection je odstraněna).
  • při načítání kolekcí (GetList, LoadAll, uložené procedury vracející kolekci) vytváří vygenerovaný kód jedno DataRecordSchema pro všechny řádky readeru a předává ho do new DataRecord(reader, dataRecordSchema, ...), místo slovníku pro každý řádek se tak alokuje jen pole hodnot (pro 1000 řádků ~50 % méně alokací).

3. Negenerovaný kód: ruční úpravy

3.1 Soubory, které generátor vytvoří jen jednou

Generátor vytváří soubory Entita.cs a EntitaCollection.cs (partial třídy, které jsou už vaše) jen jednou a jejich obsah nepřepisuje. Obsahují using System.Data.SqlClient; z doby, kdy byly vytvořeny. BL Generator 2.1.0 při přegenerování v těchto existujících souborech tento řádek sám nahradí řádkem using Microsoft.Data.SqlClient; (pokud už tam je, starý řádek odstraní). Jiné změny v nich nedělá.

using System.Data.SqlClient;   // původně
using Microsoft.Data.SqlClient; // nově

3.2 Odstraněné členy ([Obsolete])

V rámci verze 2.1.0 byly odstraněny členy, které byly dlouho označené [Obsolete]. Pokud je používáte, kód se nezkompiluje:

Odstraněno Náhrada
DataRecord(DataRow row), DataRecord(DataRow row, bool fullLoad) DataRecord(DataRow row, DataLoadPower dataLoadPower) (FullLoad / PartialLoad)
DataRecord(IDataRecord record), DataRecord(IDataRecord record, bool fullLoad) DataRecord(IDataRecord record, DataLoadPower dataLoadPower)
DataRecord.Load<T>, LoadObject, LoadString, LoadInt32, LoadDouble, LoadBoolean, LoadDateTime DataRecord.TryGet<T>(...) nebo Get<T>(...) / GetString, GetNullableInt32, ...
BusinessObjectCollection.Sort(string propertyName, bool ascending) Sort(PropertyInfo propertyInfo, SortDirection sortDirection), Sort(Comparison<TItem>) nebo Sort(IComparer<TItem>)
FieldPropertySortItem() (bez parametrů) FieldPropertySortItem(FieldPropertyInfo property) nebo FieldPropertySortItem(FieldPropertyInfo property, SortDirection direction)
MatchListMode a přetížení ReferenceCondition.CreateIn(operand, ids, mode) / CreateNotIn(operand, ids, mode) ReferenceCondition.CreateIn(operand, ids) / CreateNotIn(operand, ids) (parametr mode se už dlouho neuvažoval)

4. Connection stringy: výchozí šifrování

Microsoft.Data.SqlClient má výchozí Encrypt=True a TrustServerCertificate=False (u System.Data.SqlClient bylo Encrypt=False). DbConnector ani generátor connection string nijak neupravují. Pokud SQL Server nemá certifikát, kterému klient důvěřuje (např. self-signed na vývojovém serveru), připojení selže s chybou o řetězu certifikátů. Možnosti:

  • nainstalovat na SQL Server důvěryhodný certifikát (doporučeno pro produkci),
  • do connection stringu přidat TrustServerCertificate=True (rychlé řešení pro vývoj a testy),
  • nebo Encrypt=False (obnoví staré chování, šifrování se pak nepoužije).

Pokud connection string používá klíčová slova Asynchronous Processing nebo Context Connection, Microsoft.Data.SqlClient je nepřijme a je potřeba je odebrat.

Product Compatible and additional computed target framework versions.
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Havit.Business:

Package Downloads
Havit.Enterprise.Web

HAVIT .NET Framework Extensions - Web Class Library for HAVIT Business Layer

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 128 10/21/2026
2.1.0-pre01 90 10/20/2026
2.0.36 99 10/19/2026
2.0.35 2,428 1/12/2024
2.0.35-pre01 239 1/11/2024
2.0.34 835 10/27/2022
2.0.30 543 10/6/2022
2.0.10 740 1/25/2022
2.0.8 974 6/11/2020
2.0.7 710 6/4/2020
2.0.6 967 7/16/2019
2.0.5 767 7/3/2019
2.0.4 790 6/6/2019
2.0.3 808 6/3/2019
2.0.2 816 5/22/2019
2.0.1 817 3/21/2019

v2.1.0 (10/2026)
• Odstraněny členy označené [Obsolete]: BusinessObjectCollection.Sort(string, bool), FieldPropertySortItem(), enum MatchListMode a přetížení ReferenceCondition.CreateIn/CreateNotIn s parametrem MatchListMode. Generátor již negeneruje přepis Sort(string, bool) v *CollectionBase.
• BREAKING CHANGE: Přechod z System.Data.SqlClient na Microsoft.Data.SqlClient (závislost přes Havit.Data 2.1.0).
• BusinessObjectBase.Save a Delete: příznaky IsSaving a IsDeleting se vracejí zpět i po výjimce (ConstraintViolationException, chyba databáze). Dříve po neúspěšném Save každé další Save() objektu tiše nic neudělalo, po neúspěšném Delete každé další Delete(). Stav objektu po neúspěšném uložení se neobnovuje, opakování uložení po selhání se nepředpokládá.
• BusinessObjectCollection.SetItem (nastavení přes indexer) při zakázaných duplicitách již nevyhazuje výjimku pro prvek, který v kolekci není (IndexOf vrátil -1). Výjimka se vyhazuje jen pro skutečnou duplicitu na jiném indexu.
• BusinessObjectCollection.AddRange a RemoveAll respektují Freeze (InvalidOperationException u zamčené kolekce). AddRange při zakázaných duplicitách kontroluje duplicity vůči kolekci i uvnitř zdroje (ArgumentException, kolekce zůstane beze změny) a zdroj enumeruje pouze jednou (dříve dvakrát, což u líných dotazů znamenalo dvojí provedení projekce).
• BREAKING CHANGE (změna výsledku dotazu): DateRangeCondition.Create se zadanou pouze horní mezí používá horní mez včetně (<=), stejně jako při zadání obou mezí. Dříve bylo v tomto případě použito striktní <.
• BREAKING CHANGE: Odstraněna podpora SQL Server Compact Edition 3.5 a SQL Server 2005 (hodnoty SqlServerCe35 a SqlServer2005 enumu SqlServerPlatform z Havit.Data). Podmínka IN pro pole celých čísel používá vždy table-valued parametr IntTable, DateTime hodnoty se předávají vždy jako DateTime2. BL Generator: enum TargetPlatform obsahuje již jen SqlServer2008, přepínač -targetplatform akceptuje pouze tuto hodnotu a kolekce se předávají vždy přes IntTable (odstraněna generace pro CLR typ IntArray).
• Dokumentace: ActiveRecordBusinessObjectBase.Save i pro disconnected objekty (ConnectionMode.Disconnected) otevírá spojení a zakládá transakci (sdílenou celým grafem ukládaných objektů), databáze tedy musí být dostupná i při uložení disconnected objektů. Chování se nemění, je nově popsáno v dokumentaci Save a ConnectionMode.Disconnected.
• CollectionPropertyHolder: odložená inicializace kolekce se nyní provádí skutečně právě jednou (dříve vlákna čekající na zámku opakovaně přihlašovala handler CollectionChanged a přepisovala LoadedValue) a příznak odložené inicializace se shazuje až po nastavení Value i LoadedValue (a je volatile), takže jiné vlákno nemůže vidět LoadedValue == null. Initialize() zahazuje dosud nepoužitou odloženou hodnotu z předchozího Initialize(string) (první přístup k Value jinak vrátil původní hodnoty místo prázdné kolekce). LoadedValue před inicializací vyhazuje InvalidOperationException jako Value (dříve vracela null).
• NumberCondition.CreateIn: rozdíl krajních hodnot se počítá v typu long. Dříve pole s extrémními hodnotami (např. { 0, int.MinValue } nebo { int.MaxValue, -1 }) vyhodilo OverflowException z Math.Abs, případně se kvůli přetečení rozdílu rozhodovalo chybně.
• NumberCondition.CreateIn: hledání souvislé posloupnosti hodnot (pro podmínku BETWEEN) probíhá v jediném průchodu polem, O(n), místo odstranění duplicit, vytvoření seznamu a třídění, O(n log n); stejný postup jako v EF Core (QueryHelpers.TryGetConsecutiveRange). Vytvářené podmínky se nemění.
• PropertyInfo.Owner a PropertyName a ReferenceFieldPropertyInfo.TargetType a TargetObjectInfo před inicializací vyhazují InvalidOperationException jako ostatní vlastnosti property-info (dříve vracely null).
• Odstraněn zakomentovaný (nepoužívaný) kód.
• Opraveny překlepy a nepřesnosti v dokumentaci a komentářích (BusinessObjectBase, ActiveRecordBusinessObjectBase, PropertyHolderBase, FieldPropertyInfo, ReferenceFieldPropertyInfo, TernaryCondition, CommandBuilderOptions).
• Generovaný kód (Havit.Business.BLGenerator 2.1.0) používá using Microsoft.Data.SqlClient; je nutné přegenerovat business vrstvu a zvýšit verzi Havit.Business ve stejný okamžik.
• BL Generator při přegenerování v existujících souborech Entita.cs a EntitaCollection.cs vymění "using System.Data.SqlClient;" za "using Microsoft.Data.SqlClient;".
• BL Generator se k databázi připojuje s TrustServerCertificate=True (Microsoft.Data.SqlClient má výchozí Encrypt=True, vývojové servery často nemají důvěryhodný certifikát).
• Generovaný kód sdílí při načítání kolekcí jedno DataRecordSchema pro všechny řádky readeru (GetList, LoadAll, uložené procedury vracející kolekci), přínos se projeví po přegenerování.
• ValueOperand: rychlejší pojmenování parametrů dotazu (vlastní ordinální průchod místo DbParameterCollection.Contains, cache názvů), výrazný rozdíl pro stovky parametrů v jednom dotazu.
• IntTableOperand vyžaduje Microsoft.Data.SqlClient.SqlCommand (providerName "System.Data.SqlClient" je v DbConnectoru mapován na Microsoft.Data.SqlClient).
• Odebrány přímé závislosti na System.Buffers a System.Memory (nepoužívané, tranzitivně je přináší Microsoft.Data.SqlClient).