Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataProtection.PersistKeysToDbContext fails when using Cosmos DB EF 9. Possible included here. #59717

Open
1 task done
toiyabe opened this issue Jan 4, 2025 · 0 comments
Open
1 task done
Labels
area-dataprotection Includes: DataProtection

Comments

@toiyabe
Copy link
Contributor

toiyabe commented Jan 4, 2025

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Cosmos DB Entity Framework for .Net 9 now requires all LINQ functions to be asynchronous. When attempting to use the synchronous method, it throws the following error:

'Microsoft.EntityFrameworkCore.Database.SyncNotSupported': Azure Cosmos DB does not support synchronous I/O. Make sure to use and correctly await only async methods when using Entity Framework Core to access Azure Cosmos DB.

For example, Entity.ToList() will fail while Entity.ToListAsync() will succeed.

I have found that the following code changes to EntityFrameworkCoreXmlRepository will solve the problem. Note where I check if DB is Cosmos, and there make async calls. Someone more cleaver than I can probably simplify this.

Question, can all EF providers support asynchronous methods? If so, then maybe make this async for all and not worry if this is for Cosmos or not?

public virtual IReadOnlyCollection<XElement> GetAllElements()
{
    // forces complete enumeration
    return GetAllElementsCore().ToList().AsReadOnly();

    IEnumerable<XElement> GetAllElementsCore()
    {
        using (var scope = _services.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<TContext>();

            List<DataProtectionKey> keys;

            // Cosmos DB EF 9 supports only async methods.
            if (context.Database.IsCosmos())
            {
                keys = context.DataProtectionKeys.AsNoTracking().ToListAsync().Result;
            }
            else
            {
                keys = context.DataProtectionKeys.AsNoTracking();
            }

            foreach (var key in keys)
            {
                _logger.ReadingXmlFromKey(key.FriendlyName!, key.Xml);

                if (!string.IsNullOrEmpty(key.Xml))
                {
                    yield return XElement.Parse(key.Xml);
                }
            }
        }
    }
}

/// <inheritdoc />
public void StoreElement(XElement element, string friendlyName)
{
    using (var scope = _services.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<TContext>();
        var newKey = new DataProtectionKey()
        {
            FriendlyName = friendlyName,
            Xml = element.ToString(SaveOptions.DisableFormatting)
        };

        context.DataProtectionKeys.Add(newKey);
        _logger.LogSavingKeyToDbContext(friendlyName, typeof(TContext).Name);

        // Cosmos DB EF 9 supports only async methods.
        if (context.Database.IsCosmos())
        {
            context.SaveChangesAsync().Wait();
        }
        else
        {
            context.SaveChanges();
        }
    }
}

Expected Behavior

No response

Steps To Reproduce

Create an asp.net project, .Net 9, with a Cosmos DB database. Then add data protection using the DbContext. Here is example code that will cause the error:

// Add shared data protection here
builder.Services.AddDataProtection()
    .SetApplicationName("editor").UseCryptographicAlgorithms(
    new AuthenticatedEncryptorConfiguration
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    }).PersistKeysToDbContext<ApplicationDbContext>();

Note: The ApplicationDbContext uses Cosmos DB.

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-dataprotection Includes: DataProtection label Jan 4, 2025
toiyabe added a commit to MoonriseSoftwareCalifornia/CosmosCMS that referenced this issue Jan 4, 2025
Added custom data persister so I can continue migration to .Net 9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dataprotection Includes: DataProtection
Projects
None yet
Development

No branches or pull requests

1 participant