ef core, why does it generate this query instead of a simple insert? (save object graph with byte[] inside) and associated performance issue

For SQL Server SaveChanges batches by default. For this scenario (loading blob data), batching is actually bad, as you don't want a huge parameter set bound on the client and server, and then traversed to load. You want single-insert batches (or if your blobs are really large, SqlClient Streaming, for which you'll need to drop down to ADO.NET).

You configure this on the same line you instruct the DbContext to use SQL Server, eg:

optionsBuilder.UseSqlServer(constr, b => b.MaxBatchSize(1).UseRelationalNulls(true) );

To disable batching, and to opt out of generating queries that emulate C# null comparison semantics.

If you need to conditionally disable batching, you can add a DbContext constructor parameter that you read on OnConfiguring. EG

public class Db : DbContext
{
    bool disableBatching = false;

    public Db() : base()
    {

    }
    public Db(bool disableBatching)
    {
        this.disableBatching = true;
    }

And if you need to convince your DI container to sometimes hand out DbContexts with batching disabled, you can create a new subtype for that, as most DI containers work off type registrations. EG:

public class NoBatchingDb : Db
{
    public NoBatchingDb() : base(disableBatching: true) { }
}