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
<PackageReference Include="Havit.Business" Version="2.1.0" />
<PackageVersion Include="Havit.Business" Version="2.1.0" />
<PackageReference Include="Havit.Business" />
paket add Havit.Business --version 2.1.0
#r "nuget: Havit.Business, 2.1.0"
#:package Havit.Business@2.1.0
#addin nuget:?package=Havit.Business&version=2.1.0
#tool nuget:?package=Havit.Business&version=2.1.0
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
- Aktualizovat balíčky
Havit.BusinessaHavit.Business.BLGeneratorna 2.1.x (a případněHavit.Data, pokud ho referencujete přímo). - Odebrat případné vlastní reference na
System.Data.SqlClient. - Přegenerovat business vrstvu aktualizovaným BL Generatorem.
- Ručně upravit negenerovaný kód (soubory
Entita.csaEntitaCollection.cssi generátor při přegenerování opraví sám, viz níže). - Zkontrolovat connection stringy (výchozí
Encrypt=True) a konfiguraci. - Zkompilovat a spustit testy.
1. Závislosti
- Aktualizujte
Havit.Businessna 2.1.0. PřesHavit.Data2.1.0 přinese tranzitivněMicrosoft.Data.SqlClient7.1.1. - Odeberte z projektů závislost na NuGet balíčku
System.Data.SqlClient, pokud ji máte (na .NET Frameworku není proSystem.Data.SqlClientbalíč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.BLGeneratorve verzi 2.1.0 (generátor ze starší verze generuje kód proSystem.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ístousing System.Data.SqlClient;(všechny soubory_generated; v existujících souborechEntita.csaEntitaCollection.csgenerá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 vBusinessObjectCollectionje odstraněna). - při načítání kolekcí (
GetList,LoadAll, uložené procedury vracející kolekci) vytváří vygenerovaný kód jednoDataRecordSchemapro všechny řádky readeru a předává ho donew 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 | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- Havit.Data (>= 2.1.0)
- Havit.Services (>= 2.0.53)
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).