EF Core,投影子集合渴望加载

时间:2018-05-28 04:43:05

标签: c# entity-framework .net-core ef-core-2.0

在EF核心中,我试图用子集合来计划结果集。

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import java.security.*;
import java.io.UnsupportedEncodingException;

public class EncryptDecrypt1 {

    public static void main(String[] args) throws Exception {
        EncryptDecrypt1 a = new EncryptDecrypt1();
        String encrypted = a.encrypt("My text");
        System.out.println(encrypted);      
    }
    public String encrypt(String cleartext) throws Exception {

        try 
        {
            // encoding format needs thought
            byte[] clearTextbytes = cleartext.getBytes("UTF-8");
            final SecureRandom secureKeyRandomness = SecureRandom.getInstanceStrong();
            final KeyGenerator AES_keyInstance = KeyGenerator.getInstance("AES");
            AES_keyInstance.init(128, secureKeyRandomness);
            final SecretKey secretKey = AES_keyInstance.generateKey();
            final Cipher AES_cipherInstance = Cipher.getInstance("AES/GCM/NoPadding");
            AES_cipherInstance.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedText = AES_cipherInstance.doFinal(clearTextbytes);

            byte[] iv = AES_cipherInstance.getIV();
            byte[] message = new byte[12 + clearTextbytes.length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(encryptedText, 0, message, 12, encryptedText.length);

            return decrypt(message, secretKey);
        } 
        catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) 
        {
            e.printStackTrace();
        }
        return "something went wrong with encrypt";
    } // encrypt.

    public String decrypt(byte[] encryptedText, SecretKey secretKey) throws Exception {
        try 
        {
            final Cipher AES_cipherInstance = Cipher.getInstance("AES/GCM/NoPadding");
            GCMParameterSpec params = new GCMParameterSpec(128, encryptedText, 0, 12);
            AES_cipherInstance.init(Cipher.DECRYPT_MODE, secretKey, params);
            byte[] decryptedText = AES_cipherInstance.doFinal(encryptedText, 12, encryptedText.length - 12);
            return new String(decryptedText, "UTF-8");
        } 
        catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) 
        {
            e.printStackTrace();
        }
        return "something went wrong with decrypt";
    }

}

然而,当执行此操作时,BNames集合是惰性的,因此当它被枚举时,它会触发每行的单独查询。例如,对于B集合中的2个项目。

 ctx.As.Select(a => new
    {
        AId = a.Id,
        BNames = a.Bs.Select(x=>x.Name) //SubCollection
    })

在EF6中,相同的查询会产生以下结果(正如我所料):

[a].[Id] AS [AId] FROM [As] AS [a]

p_executesql N'SELECT [x].[Name]
FROM [Bs] AS [x]
WHERE @_outer_Id = [x].[AId]',N'@_outer_Id int',@_outer_Id=1

p_executesql N'SELECT [x].[Name]
FROM [Bs] AS [x]
WHERE @_outer_Id = [x].[AId]',N'@_outer_Id int',@_outer_Id=2

如何让EF热切加载子集SELECT [Extent1].[Id] AS [Id], [Project1].[C1] AS [C1], [Project1].[Name] AS [Name] FROM [dbo].[A] AS [Extent1] LEFT OUTER JOIN (SELECT [Extent2].[Name] AS [Name], [Extent2].[A_Id] AS [A_Id], 1 AS [C1] FROM [dbo].[B] AS [Extent2] ) AS [Project1] ON [Extent1].[Id] = [Project1].[A_Id] ORDER BY [Extent1].[Id] ASC, [Project1].[C1] ASC

注意:这与包含BNames的子实体的问题不同,因为这是自定义投影,而不是导航属性。在此使用.Include会导致错误。

此处有完整的回购代码:https://gist.github.com/lukemcgregor/692834629da09b21d5a35515e86c9002

1 个答案:

答案 0 :(得分:3)

这可以在EF Core 2.1中使用其相关子查询优化。

您需要更新到EF Core 2.1并进行一些小修改,以便通过向子查询添加let imageSource = new ImageSource(); let loadedSource64 = imageSource.loadFromBase64(BASE_64_STRING_FROM_API_CALL); if (loadedSource64 ) { let image= <Image>this.imageElement.nativeElement; image.imageSource = this.imageSource; } 来选择优化:

.ToList()

请参阅Optimization of correlated subqueries中的New features in EF Core 2.1