我有客户课程:
public class Client
{
public int Id { get; set; }
public ClientId ClientId { get; set; }
}
和值对象(记录)
ClientId
:
public record ClientId
{
private ClientId() { }
public ClientId(string clientId)
{
if (!CanCreate(clientId))
throw new ArgumentException($"'{nameof(clientId)}' must be 32 bytes long Base64Url encoded string.");
Value = clientId;
}
public string Value { get; private init; }
public static bool CanCreate(string clientId)
{
return !string.IsNullOrEmpty(clientId) && Base64UrlEncoder.Validate(clientId, out int length) && length == 32;
}
}
当我想通过
Client
找到ClientId
时:
public async Task<T?> FindByClientId<T>(ClientId clientId, Expression<Func<Client, T>> selector, CancellationToken cancellationToken = default,
params Expression<Func<Client, object>>[] include)
{
if (selector is null) throw new ArgumentNullException(nameof(selector));
var baseQuery = _dbContext.Clients.AsNoTrackingWithIdentityResolution()
.Where(p => p.ClientId == clientId);
return await include.Aggregate(baseQuery, (current, inc) => current.Include(inc))
.Select(selector)
.SingleOrDefaultAsync(cancellationToken);
}
我总是收到此错误:
System.InvalidOperationException: No backing field could be found for property 'ClientId.ClientId' and the property does not have a getter.
这是我的
Client
配置:
public class ClientConfiguration : IEntityTypeConfiguration<Client>
{
public void Configure(EntityTypeBuilder<Client> builder)
{
builder.OwnsOne(p => p.ClientId, buildAction =>
{
buildAction.Property(p => p.Value)
.HasColumnName(nameof(Client.ClientId))
.HasMaxLength(43);
buildAction.HasIndex(p => p.Value).IsUnique();
});
}
}
为什么这不起作用?我做错了什么?
我遇到了同样的问题,并且该问题似乎仅在对值对象使用唯一约束时才会发生:
buildAction.HasIndex(p => p.Value).IsUnique()
。
解决方案涉及将与
ClientId
类中的 Id
字段(在您的情况下为 Client
)具有相同类型的 int
字段添加到 ClientId
值对象。尽管在您的特定场景中包含此字段可能看起来很尴尬,但 EF Core 将其用作将 ClientId 值对象链接回客户端实体的外键。无论字段是否存储为同一个表中的列,都会发生这种链接。
public record ClientId
{
public int ClientId { get; private set; }
// rest of the code...
}
添加属性后,一切都应该运行良好,无需创建迁移。请注意,添加的属性应该有一个 setter,无论是公共的还是私有的。