Sto importando i dati da un DB legacy a un nuovo progetto, sono un po 'confuso su alcuni degli SQL generati da EF Core (li ho guardati nella visualizzazione dell'output in quanto funzionava molto male rispetto a quanto mi aspettassi).
Sto prendendo di mira SQL Server e sto creando oggetti con sottoproprietà di tipo Image (un poco) ecco un esempio di come viene utilizzato su un oggetto con tale proprietà:
MyObject.Thumbnail = new Image()
{
Name = Thumbnail.GetValue("Name"),
OriginalData = ImageData,
Data = ImageData,
Width = bmp.Width,
Height = bmp.Height,
Format = ImageFormat.Jpg
};
Sono rimasto confuso sull'SQL generato (e, a dire il vero, non lo capisco, sta dichiarando una tabella temporanea e quindi si fonde? Perché?) E dalle sue prestazioni (ci vogliono 17 secondi per inserire 10 elementi con 2 immagini ognuna delle proprietà, sto eseguendo SQL Server localmente sullo stesso computer del processo core .net che esegue le query, quindi non c'è latenza di rete e larghezza di banda inifnite e array di byte e abbastanza piccolo per cominciare, principalmente nell'intervallo di 300kb) .
Le prestazioni previste rimuoveranno da uno a due zero.
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (17,211ms) [Parameters=[@p0='?' (Size = -1) (DbType = Binary), @p1='?' (Size = 4000), @p2='?' (DbType = Int32), @p3='?' (DbType = Int32), @p4='?' (Size = 4000), @p5='?' (Size = -1) (DbType = Binary), @p6='?' (DbType = Int32), @p7='?' (Size = -1) (DbType = Binary), @p8='?' (Size = 4000), @p9='?' (DbType = Int32), @p10='?' (DbType = Int32), @p11='?' (Size = 4000), @p12='?' (Size = -1) (DbType = Binary), @p13='?' (DbType = Int32), @p14='?' (Size = -1) (DbType = Binary), @p15='?' (Size = 4000), @p16='?' (DbType = Int32), @p17='?' (DbType = Int32), @p18='?' (Size = 4000), @p19='?' (Size = -1) (DbType = Binary), @p20='?' (DbType = Int32), @p21='?' (Size = 8000) (DbType = Binary), @p22='?' (Size = 4000), @p23='?' (DbType = Int32), @p24='?' (DbType = Int32), @p25='?' (Size = 4000), @p26='?' (Size = 8000) (DbType = Binary), @p27='?' (DbType = Int32), @p28='?' (Size = -1) (DbType = Binary), @p29='?' (Size = 4000), @p30='?' (DbType = Int32), @p31='?' (DbType = Int32), @p32='?' (Size = 4000), @p33='?' (Size = -1) (DbType = Binary), @p34='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DECLARE @inserted0 TABLE ([Id] int, [_Position] [int]);
MERGE [Images] USING (
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, 0),
(@p7, @p8, @p9, @p10, @p11, @p12, @p13, 1),
(@p14, @p15, @p16, @p17, @p18, @p19, @p20, 2),
(@p21, @p22, @p23, @p24, @p25, @p26, @p27, 3),
(@p28, @p29, @p30, @p31, @p32, @p33, @p34, 4)) AS i ([Data], [Description], [Format], [Height], [Name], [OriginalData], [Width], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([Data], [Description], [Format], [Height], [Name], [OriginalData], [Width])
VALUES (i.[Data], i.[Description], i.[Format], i.[Height], i.[Name], i.[OriginalData], i.[Width])
OUTPUT INSERTED.[Id], i._Position
INTO @inserted0;
Per i batch di SQL Server SaveChanges per impostazione predefinita. Per questo scenario (caricamento dei dati BLOB), il batching è effettivamente errato, poiché non si desidera un enorme set di parametri associato al client e al server, quindi attraversato per il caricamento. Desideri batch a inserimento singolo (o se i tuoi BLOB sono davvero grandi, SqlClient Streaming , per il quale dovrai passare a ADO.NET).
Si configura questo sulla stessa riga in cui si indica a DbContext di utilizzare SQL Server, ad esempio:
optionsBuilder.UseSqlServer(constr, b => b.MaxBatchSize(1).UseRelationalNulls(true) );
Per disabilitare il batch e disattivare la generazione di query che emulano la semantica del confronto null C #.
Se è necessario disabilitare in modo condizionale il batch, è possibile aggiungere un parametro del costruttore DbContext letto su OnConfiguring. PER ESEMPIO
public class Db : DbContext
{
bool disableBatching = false;
public Db() : base()
{
}
public Db(bool disableBatching)
{
this.disableBatching = true;
}
E se hai bisogno di convincere il tuo contenitore DI a volte a distribuire DbContexts con il batch disabilitato, puoi creare un nuovo sottotipo per questo, poiché la maggior parte dei contenitori DI funziona con registrazioni di tipo. PER ESEMPIO:
public class NoBatchingDb : Db
{
public NoBatchingDb() : base(disableBatching: true) { }
}