dotnet / dotnet/extensions

[HybridCache] [Question] Serialization / Deserialization does not behave like in EF Core

Open
#6,479 0 comments 0 reactions 0 assignees View on GitHub
area-caching-hybrid
Dominant language
C#
Stars
3.2k
Forks
894
Avg merge
1d 12h
Merged PRs (30d)
23

Description

Hi Team,

this is more a question or something that I noticed while trying HybridCache and EF Core and DDD together.

When I use EF Core (and Cosmos DB) with this class definition, the serialization works expected.
EF core uses the private empty constructor to initialize all fields / properties and in my own code I use the public constructor.

After I get the Group object from EF, I put it into the HybridCache (InMemory) via the HybridCache.GetOrCreateAsync method and the object that is returned has default values set for:
- CreatedBy
- CreatedAt
- ModifiedBy
- ModifiedAt
- ETag

That is because HybridCache uses the public constructor by default and NOT the private empty constructor like EF Core.

A workaround is to implement a specific private constructor with the [JsonConstructor] attribute for HybridCache.

```csharp
public class Group : AggregateRoot, IOwnable, IVersionable
{
public string Name { get; private set; }
public string? Description { get; private set; }
public IReadOnlyList MemberUserIds => _memberUserIds.AsReadOnly();
private List _memberUserIds = [];

public int Version { get; protected set; } = 1;

///
/// For CosmosDB concurrency
///
public string ETag { get; } = "";

public Guid OwnerId { get; private set; }

public Guid? ImageId { get; private set; }

private Group()
{
// For EF Core
// EF core uses this and can initialize alle fields and properties as expected
}

// This attribute is needed so that HybridCache knows which constructor to use.
// Otherwise it would use the public constructor.
[JsonConstructor]
private Group(Guid id, string name, string eTag, DateTime createdAt, Guid createdBy, DateTime modifiedAt, Guid modifiedBy, Guid ownerId, IReadOnlyList memberUserIds, string? description = null, Guid? imageId = null)
{
// For the HybridCache Serializer. Otherwise it would not be able to set createdAt, createdBy, modifiedAt, modifiedBy, memberUserIds and eTag...
Id = id;
Name = name;
Description = description;
ImageId = imageId;
ETag = eTag;
OwnerId = ownerId;

SetCreationMetadata(new AuditMetadata(createdBy, createdAt));
SetModifiedMetadata(new AuditMetadata(modifiedBy, modifiedAt));

_memberUserIds = memberUserIds.ToList() ?? [];
}

public Group(Guid id, string name, string? description = null, Guid? imageId = null)
{
Id = id;
ValidateName(name);
Name = name;
Description = description;
ImageId = imageId;

RaiseEvent(new Created(Id));
}

// Other code...
}
```

The base class and interfaces provide these definitions for the Group class

```csharp
public Guid Id { get; protected set; }

public Guid CreatedBy { get; private set; }
public DateTime CreatedAt { get; private set; }
public Guid ModifiedBy { get; private set; }
public DateTime ModifiedAt { get; private set; }
```

Is this intended behavior?
I would have expected that the serialization would behave just like in EF Core.
Can HybridCache be configured to behave like EF Core in this area?

Best regards

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.