Parent/Child with EF6 child collection always null - c#

When ever I pull a MyList object via EF, the parent is associated correctly but the Children collection is always null. Not sure what I'm doing wrong, pretty much every article shows to do it this way.
Database
CREATE TABLE [dbo].[MyList] (
[MyListId] BIGINT IDENTITY (1, 1) NOT NULL,
[ParentMyListId] BIGINT NULL,
CONSTRAINT [PK_MyList] PRIMARY KEY CLUSTERED ([MyListId] ASC) WITH (FILLFACTOR = 90),
CONSTRAINT [FK_MyList_MyList_MyListId] FOREIGN KEY (ParentMyListId) REFERENCES MyList(MyListId)
);
Model
public class MyList
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long MyListId { get; set; }
public long? ParentMyListId { get; set; }
[ForeignKey("ParentMyListId")]
public virtual List MyListParent { get; set; }
public virtual ICollection<MyList> MyListChildren { get; set; }
}
DBContext
public class MyContext : DbContext
{
public MyContext() : base(Properties.Settings.Default.DbContext)
{
Configuration.LazyLoadingEnabled = false;
}
public DbSet<MyList> MyLists { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyList>()
.ToTable("MyList", "dbo")
.HasOptional(x => x.MyListParent)
.WithMany(x => x.MyListChildren)
.HasForeignKey(x => x.ParentMyListId)
.WillCascadeOnDelete(false);
}
base.OnModelCreating(modelBuilder);
}

I tried with same structure in EF 6.1.3 version and it worked like charm. I added image of output and data present in db. The only thing that might stopped working if you disable loading in configuration. I hope it work for you please try my sample code.
// Your entity class I added name property to show you the results
public class MyList
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long MyListId { get; set; }
public long? ParentMyListId { get; set; }
public string Name { get; set; }
[ForeignKey("ParentMyListId")]
public virtual MyList MyListParent { get; set; }
public virtual ICollection<MyList> MyListChildren { get; set; }
}
// DBContext please note no configuration properties set just default constructor
// you need t check here if you have set soemthing here
public class TestContext : DbContext
{
public TestContext()
: base("name=TestConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyList>()
.ToTable("MyList", "dbo")
.HasOptional(x => x.MyListParent)
.WithMany(x => x.MyListChildren)
.HasForeignKey(x => x.ParentMyListId)
.WillCascadeOnDelete(false);
}
public virtual DbSet<MyList> Lists { get; set; }
}
The console app to show result:
static void Main(string[] args)
{
using (var ctx = new TestContext())
{
// for testing to see al working
//this is important to read the entity first .
var parent = ctx.Lists.ToList();
foreach (var p in parent)
{
foreach (var child in p.MyListChildren)
{
Console.WriteLine(string.Format(#"Parent Name {0} has child with name {1}", p.Name, child.Name));
}
}
}
Console.ReadLine();
}
Output of app and data in database ...

Related

How to properly setup ApplicationUser and FriendRequest entities to allow for cascade deleting

I have the traditional ApplicationUser (IdentityUser), and that user can send a friend request to another ApplicationUser. I currently have the following general entity classes:
public class ApplicationUser : IdentityUser
{
public virtual List<DeviceToken> DeviceTokens { get; set; } = new List<DeviceToken>();
public string DisplayName { get; set; }
}
public class FriendRequest
{
public int Id { get; set; }
public DateTime DateRequested { get; set; }
public ApplicationUser Requester { get; set; }
public ApplicationUser Receiver { get; set; }
}
I have ran database-update etc and this is working fine. However when I go into my SQLServer to try to delete an ApplicationUser, it tells me that The DELETE statement conflicted with the REFERENCE constraint "FK_FriendRequest_AspNetUsers_RequesterId".
So I have decided to implement a cascade delete flow from the ApplicationUser to the friend requests that they are part of.
I have tried the resource on here by Microsoft on configuring cascade delete but I cannot figure out how to apply it to my case:
builder.Entity<ApplicationUser>()
.HasMany(e => e.FriendRequests)//No such property, no idea how to address
.OnDelete(DeleteBehavior.ClientCascade);
How do I set up this cascade delete scenario?
Also how do I add a property to ApplicationUser that refers to all the FriendRequests they are part of, and make sure EFCore knows I am referring to that existing FriendRequest entity/table?
Update
Following the suggested approach of adding a virtual property to ApplicationUser, would this be way forward:
public class ApplicationUser : IdentityUser
{
public virtual List<DeviceToken> DeviceTokens { get; set; } = new List<DeviceToken>();
public string DisplayName { get; set; }
public ICollection<FriendRequest> FriendRequests { get; }
}
builder.Entity<ApplicationUser>()
.HasMany(u => u.FriendRequests)
.WithOne(u => u.Requester)
.OnDelete(DeleteBehavior.ClientCascade); //not sure about this
builder.Entity<ApplicationUser>()
.HasMany(u => u.FriendRequests)
.WithOne(u => u.Requester)
.OnDelete(DeleteBehavior.ClientCascade); //not sure about this
Your ApplicationUser needs 2 virtual ICollections.
public class ApplicationUser
{
public int Id { get; set; }
public string DisplayName { get; set; }
public virtual ICollection<FriendRequest> FriendRequestsAsRequestor { get; set; }
public virtual ICollection<FriendRequest> FriendRequestsAsReceiver { get; set; }
}
public class FriendRequest
{
public int Id { get; set; }
public DateTime DateRequested { get; set; }
public int RequestorId { get; set; }
public ApplicationUser Requestor { get; set; }
public int ReceiverId { get; set; }
public ApplicationUser Receiver { get; set; }
}
public class ApplicationUserConfig : IEntityTypeConfiguration<ApplicationUser>
{
public void Configure(EntityTypeBuilder<ApplicationUser> builder)
{
builder.HasMany(au => au.FriendRequestsAsRequestor)
.WithOne(fr => fr.Requestor)
.HasForeignKey(fr => fr.RequestorId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasMany(au => au.FriendRequestsAsReceiver)
.WithOne(fr => fr.Receiver)
.HasForeignKey(fr => fr.ReceiverId)
.OnDelete(DeleteBehavior.Cascade);
}
}
Use:
void AddFriendRequest(int requestorId, int receiverId)
{
var ctxt = new DbContext();
FriendRequest fr = new FriendRequest
{
RequestorId = requestorId;
ReceiverId = receiverId;
DateRequested = DateTime.Now;
}
ctxt.FriendRequests.Add(fr);
ctxt.SaveChanges();
}
List<FriendRequest> GetFriendRequests()
{
var ctxt = new DbContext();
return ctxt.FriendRequests
.Include(fr => fr.Requestor)
.Include(fr => fr.Receiver)
.ToList();
}
ApplicationUser GetUserWithFriendRequests(int id)
{
var ctxt = new DbContext();
return ctxt.ApplicationUser
.Include(au => au.FriendRequestsAsRequestor)
.Include(au => au.FriendRequestsAsReceiver)
.SingleOrDefault(au => au.Id == id);
}
I have tried the resource on here by Microsoft on configuring cascade delete but I cannot figure out how to apply it to my case:
builder.Entity<ApplicationUser>()
.HasMany(e => e.FriendRequests)//No such property, no idea how to address
.OnDelete(DeleteBehavior.ClientCascade);
From the doc of DeleteBehavior :
ClientCascade : For entities being tracked by the DbContext, dependent entities will be deleted when the related principal is deleted. If the database has been created from the model using Entity Framework Migrations or the EnsureCreated() method, then the behavior in the database is to generate an error if a foreign key constraint is violated.
In this case, it's the client (the .NET app) and not the DB that ensure the cascade delete. If the client fail to do the cascade delete (related entity not tracked), the db will generate the error you see.
Maybe the DeleteBehavior.Cascade is more appropriate to your code first scenario :
Cascade : For entities being tracked by the DbContext, dependent entities will be deleted when the related principal is deleted. If the database has been created from the model using Entity Framework Migrations or the EnsureCreated() method, then the behavior in the database is the same as is described above for tracked entities. Keep in mind that some databases cannot easily support this behavior, especially if there are cycles in relationships, in which case it may be better to use ClientCascade which will allow EF to perform cascade deletes on loaded entities even if the database does not support this. This is the default for required relationships. That is, for relationships that have non-nullable foreign keys.
If you try this, you go with this SQL script migration (I assume the SGBDR is SQL Server) :
CREATE TABLE [ApplicationUser] (
[Id] int NOT NULL IDENTITY,
[DisplayName] nvarchar(max) NULL,
CONSTRAINT [PK_ApplicationUser] PRIMARY KEY ([Id])
);
GO
CREATE TABLE [FriendRequests] (
[Id] int NOT NULL IDENTITY,
[DateRequested] datetime2 NOT NULL,
[RequesterId] int NULL,
[ReceiverId] int NULL,
CONSTRAINT [PK_FriendRequests] PRIMARY KEY ([Id]),
CONSTRAINT [FK_FriendRequests_ApplicationUser_ReceiverId] FOREIGN KEY ([ReceiverId]) REFERENCES [ApplicationUser] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_FriendRequests_ApplicationUser_RequesterId] FOREIGN KEY ([RequesterId]) REFERENCES [ApplicationUser] ([Id]) ON DELETE CASCADE
);
GO
And when it's apply, this produce this error :
Introducing FOREIGN KEY constraint 'FK_FriendRequests_ApplicationUser_RequesterId' on table 'FriendRequests' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
First time I see this error, then I will refer to this question with #onedaywhen's answer :
SQL Server does simple counting of cascade paths and, rather than trying to work out whether any cycles actually exist, it assumes the worst and refuses to create the referential actions (CASCADE)...
A no perfect solution is to use DeleteBehavior.Cascade and ensure all related entities are tracked before the delete :
public class ApplicationUser
{
public int Id { get; set; }
public string DisplayName { get; set; }
public ICollection<FriendRequest> RequestedRequests { get; set; }
public ICollection<FriendRequest> RecevedRequests { get; set; }
}
public class FriendRequest
{
public int Id { get; set; }
public DateTime DateRequested { get; set; }
public ApplicationUser Requester { get; set; }
public ApplicationUser Receiver { get; set; }
}
public class MyDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer("***");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<FriendRequest>()
.HasOne(r => r.Requester)
.WithMany(u => u.RequestedRequests)
.OnDelete(DeleteBehavior.ClientCascade);
modelBuilder.Entity<FriendRequest>()
.HasOne(r => r.Receiver)
.WithMany(u => u.RecevedRequests)
.OnDelete(DeleteBehavior.ClientCascade);
}
public DbSet<ApplicationUser> Users { get; set; }
public DbSet<FriendRequest> FriendRequests { get; set; }
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
PrepareUserToDeleting();
return base.SaveChangesAsync();
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
PrepareUserToDeleting();
return base.SaveChanges();
}
private void PrepareUserToDeleting()
{
// For each deleted user entity
foreach(var entry in ChangeTracker.Entries<ApplicationUser>().Where(e => e.State == EntityState.Deleted))
{
var user = entry.Entity;
// If RecevedRequests isn't loaded
if (user.RecevedRequests == null)
{
//Then load RecevedRequests
entry.Collection(u => u.RecevedRequests).Load();
}
// Idem with RequestedRequests
if (user.RequestedRequests == null)
{
entry.Collection(u => u.RequestedRequests).Load();
}
}
}
}

Circular dependency on delete (EF core)

I have two classes in my DB that reference each other, like in the example below.
Parent can have any number of Child objects, and I set a foreign key constraint to have Child.ParentID reference Parent.ID; setting DeleteBehavior.Cascade for the relation ensures that when a Parent is deleted all Child objects are deleted as well.
The problem is that I also need a reference to one of the Child objects in the Parent class, called PreferredChild in the example below. I was expecting that creating a constraint between Parent.PreferredChildId and Child.ID would work if I set DeleteBehavior.SetNull, but what actually happens is that when I delete a Parent object, if PreferredChildID is set, I get this exception:
System.InvalidOperationException: 'Unable to save changes because a circular dependency was detected in the data to be saved: 'Parent [Deleted] PreferredChild PreferredParent { 'PreferredChildID' } <- Child [Deleted] Parent Children { 'ParentID' } <- Parent [Deleted]'.'
Is there a way to model this so that I can delete a Parent object without unsetting the PreferredChildID first?
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
public class Parent {
public int? ID { get; set; }
public int? PreferredChildID { get; set; }
public virtual Child PreferredChild { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child {
public int? ID { get; set; }
public int? ParentID { get; set; }
public virtual Parent Parent { get; set; }
public virtual Parent PreferringParent { get; set; }
}
public class TestContext : DbContext {
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) {
options.UseSqlite("Data Source=test.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
// I would like to configure the model so that when a Parent is deleted,
// all Children are deleted. Using SetNull on PreferredChildID to avoid object
// being deleted twice
modelBuilder
.Entity<Child>()
.HasOne(c => c.PreferringParent)
.WithOne(p => p.PreferredChild)
.HasForeignKey<Parent>(p => p.PreferredChildID)
.OnDelete(DeleteBehavior.SetNull);
modelBuilder
.Entity<Child>()
.HasOne(c => c.Parent)
.WithMany(p => p.Children)
.HasForeignKey(c => c.ParentID)
.OnDelete(DeleteBehavior.Cascade);
}
}
class Program {
static void Main(string[] args) {
using (var context = new TestContext()) {
var parent = new Parent();
context.Parents.Add(parent);
context.SaveChanges();
var child1 = new Child { ParentID = parent.ID };
var child2 = new Child { ParentID = parent.ID };
context.Children.AddRange(child1, child2);
context.SaveChanges();
parent.PreferredChildID = child2.ID;
context.SaveChanges();
// This explodes
context.Parents.Remove(parent);
context.SaveChanges();
}
}
}
Why not just do the following?
public class Parent
{
public int? ID { get; set; }
public int? LastChildID => LastChild?.ID;
public virtual Child LastChild => Children?.LastOrDefault();
public virtual ICollection<Child> Children { get; set; }
}
Edit: After OP has edited his question, it's more clear what he wants.
I suggest adding a third table like this
CREATE TABLE [dbo].[PreferredChilds] (
[ParentId] INT NOT NULL,
[PreferredChild] INT NOT NULL,
PRIMARY KEY CLUSTERED ([ParentId] ASC, [PreferredChild] ASC),
FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Parents] ([Id]),
FOREIGN KEY ([PreferredChild]) REFERENCES [dbo].[Children] ([Id])
);
This way you don't have any problem with circular dependencies.
If you delete the parent, the entry in the preferredchilds and children table will also gets deleted.

ef core: mapping value object using OwnsMany requires primary key to be defined

I have a class
public class Document
{
public string TranId { get; set; }
public Record Record { get; set; }
public List<Error> Errors { get; set; }
}
public class Record
{
public string TranId { get; set; }
public List<DataResult> DataResults { get; set; }
}
public class DataResult
{
public string DataSourceName { get; set; }
public List<DataField> DataFields { get; set; }
public List<CustomField> CustomFields { get; set; }
}
I want to map Record and DataResult classes as Value objects so I tried to map as
public void Configure(EntityTypeBuilder<Document> builder)
{
builder.ToTable("Document");
builder.HasKey(x => x.TranId);
builder.OwnsOne(a => a.Record, a =>
{
a.ToTable("Doc_Record");
a.Property(p => p.TranId).HasMaxLength(100)
.HasColumnName("TranID")
.HasDefaultValue("");
a.OwnsMany(x => x.DataResults, x =>
{
x.ToTable("Doc_Rec_DataResults");
x.Property(p => p.DataSourceName).HasMaxLength(150)
.HasColumnName("DataSourceName")
.HasDefaultValue("");
});
}
}
When I try to add this migration it errors with a message:
The entity type 'DataResult' requires a primary key to be defined.
And why it requires primary key cause I'm trying to map as a value
object?
Someone suggested using this link and I try to add
a.OwnsMany(x => x.DataResults, x =>
{
x.WithOwner().HasForeignKey("RecordId");
x.ToTable("Doc_Rec_DataResults");
x.Property(p => p.DataSourceName).HasMaxLength(150)
.HasColumnName("DataSourceName")
.HasDefaultValue("");
});
but this approach is not working cause WithOwner is available from .net core 3 where I'm using .net core 2 (and do I really need to add RecordId property into Record class (it's a value object).
It would be great if someone can provide an example of how to map collection of value objects with OwnsMany in EF Core 2.
In this ef core 2.2 example, we have a Company that owns a collection of Addresses, here's the implementation. note that i omitted some useful code to stick to the point, refer to the full example for further explanation. Also note that this feature OwnsMany() is not available in pre ef core 2.2
public class CompanyAddress
{
public string City { get; }
public string AddressLine1 { get; }
}
public class Company
{
private List<CompanyAddress> addresses = new List<CompanyAddress>();
public Guid Id { get; }
public string Name { get; }
public IEnumerable<CompanyAddress> Addresses { get => this.addresses; }
public void AssignAddress(CompanyAddress address)
{
var exists = this.addresses.Contains(address);
if (!exists)
{
this.addresses.Add(address);
}
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Company>().OwnsMany<CompanyAddress>("Addresses", a =>
{
a.HasForeignKey("CompanyId");
a.Property(ca => ca.City);
a.Property(ca => ca.AddressLine1);
a.HasKey("CompanyId", "City", "AddressLine1");
});
}
here's a repo of full solution for the article's owner

EF6 Configuring a Required-to-Optional Relationship (One-to–Zero-or-One

I have two database tables called
SegmentSet
SegmentSetGeometry
They both have primary key called SegmentSetId. (The SegmentSetGeometry (dependent) segmentSetId is foreign key to SegmentSet (primary)).
SegmentSets can have 0 or 1 SegmentSetGeometries
I have two classes representing these tables called SegmentSet and SegmentSetGeometry:
public class SegmentSet
{
public long SegmentSetId { get; set; }
// ...
public virtual SegmentSetGeometry SegmentSetGeometry { get; set; }
}
public class SegmentSetGeometry
{
public long SegmentSetId { get; set; }
public DbGeometry Geometry { get; set; }
public virtual SegmentSet SegmentSet { get; set; }
}
Here are their configurations:
public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
{
public SegmentSetConfiguration()
{
ToTable("SegmentSet");
HasKey(x => x.SegmentSetId);
// ...
HasOptional(x => x.SegmentSetGeometry)
.WithRequired(x => x.SegmentSet);
}
}
public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
{
public SegmentSetGeometryConfiguration()
{
ToTable("SegmentSetGeometry");
HasKey(x => x.SegmentSetId);
}
}
When attempting to get a SegmentSet from the database the following error shows up:
Invalid column name 'SegmentSet_SegmentSetId'.
I found this reference https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/relationships and decided to switch the relationship and tried:
public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
{
public SegmentSetConfiguration()
{
ToTable("SegmentSet");
HasKey(x => x.SegmentSetId);
// ...
}
}
public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
{
public SegmentSetGeometryConfiguration()
{
ToTable("SegmentSetGeometry");
HasKey(x => x.SegmentSetId);
HasRequired(x => x.SegmentSet)
.WithOptional(x=>x.SegmentSetGeometry);
}
}
But still doesn't work. I am using the example they give and it's not working, and I have looked at all the similar stack overflows and still not working
To map these two together, you should map from the required side of the relationship, and only that one side. Mapping both sides can lead to EF getting a bit garbled which may be causing your issue.
public class SegmentSet
{
public long SegmentSetId { get; set; }
// ...
public virtual SegmentSetGeometry Geometry { get; set; }
}
public class SegmentSetGeometry
{
public long SegmentSetId { get; set; }
// ...
public virtual SegmentSet SegmentSet { get; set; }
}
public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
{
public SegmentSetConfiguration()
{
ToTable("SegmentSets");
HasKey(x => x.SegmentSetId);
// Note: Do not map the HasOptional here... Only map the required on the other side.
}
}
public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
{
public SegmentSetGeometryConfiguration()
{
ToTable("SegmentSetGeometries");
HasKey(x => x.SegmentSetId);
HasRequired(x => x.SegmentSet)
.WithOptional(x=>x.Geometry);
}
}
That should work as expected using the PK's on each table for the 1..0/1 relationship.
Edit: It's also worth checking that the Entity configurations are being loaded. That might explain EF falling back on convention. In the DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.AddFromAssembly(GetType().Assembly);
}
The above assumes the Entity Type Configs are in the same assembly as the DbContext definition. Otherwise: typeof(SegmentSetGeometryConfiguration).Assembly would do the trick.

Define FK names in many-to-many relationship

I what have many-to-many relationship between two entities. Everything works fine. Is there a way to define names of FKs in intermediate table(StoresPushNotifications)?
The reason to ask is that mysql do not allow to define long constraint names. It generates random FK in case. It breaks migration when I try to set migration to an earlier step.
[Table("Stores")]
public class StoreEntity
{
[Key]
public int Id { get; set; }
public virtual ICollection<PushNotificationEntity> PushNotifications { get; set; }
}
[Table("PushNotifications")]
public class PushNotificationEntity
{
[Key]
public int Id { get; set; }
public ICollection<StoreEntity> Stores { get; set; }
}
In my Context file,
modelBuilder.Entity<StoreEntity>()
.HasMany<PushNotificationEntity>(s => s.PushNotifications)
.WithMany(c => c.Stores)
.Map(cs =>
{
cs.MapLeftKey("StoreId");
cs.MapRightKey("PushNotificationId");
cs.ToTable("StoresPushNotifications");
});
I had a similar problem and it was actually related to the migration key lengthrather than the foreign keys.
I resolved by modifying the migration configuration method to:
internal sealed class Configuration : DbMigrationsConfiguration<CCDatabase.CCDbContext>
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations";
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
SetHistoryContextFactory("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema));
}
and then adding this method to limit the key lengths
public class MySqlHistoryContext : HistoryContext
{
public MySqlHistoryContext(DbConnection connection, string defaultSchema) : base(connection, defaultSchema)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<HistoryRow>().Property(h => h.MigrationId).HasMaxLength(100).IsRequired();
modelBuilder.Entity<HistoryRow>().Property(h => h.ContextKey).HasMaxLength(200).IsRequired();
}
}

Categories

Resources