I have this code in EF 6.2
public class ClientNotificationMap : EntityTypeConfiguration<ClientNotification>
{
public ClientNotificationMap()
{
HasKey(x => x.RelationalId);
Property(x => x.SubscriptionId)
.IsRequired()
.HasMaxLength(400)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
}
}
which I want to migrate to Core 2.2
public class ClientNotificationMap : IEntityTypeConfiguration<ClientNotification>
{
public ClientNotificationMap()
{
}
public void Configure(EntityTypeBuilder<ClientNotification> builder)
{
builder.HasKey(x => x.RelationalId);
builder.Property(x => x.SubscriptionId)
.IsRequired()
.HasMaxLength(400)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
}
}
Does anyone know how to change the
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
In Core it doesn't seem to be supported. Also I don't find anything relative to the web.
In the end I wrote the code
builder.HasIndex(x => x.SubscriptionId)
.IsUnique();
builder.Property(x => x.SubscriptionId)
.IsRequired()
.HasMaxLength(400);
it compiles at least
It should be something like this:
builder.HasIndex(x => new { x.SubscriptionId})
.HasDatabaseName("IX_SubscriptionId")
.HasFilter(null)
.IsUnique(true);
Related
I have a model containing these classes:
Curriculum class has several SessionTimes and other classes use these entities.
The configuration classes for them are:
public class SessionAttendanceConfiguration : EntityTypeConfiguration<SessionAttendance>
{
public SessionAttendanceConfiguration()
{
HasOptional(x => x.Session)
.WithMany(x => x.SessionAttendance)
.WillCascadeOnDelete(false);
}
}
public class SessionTimeConfiguration : EntityTypeConfiguration<SessionTime>
{
public SessionTimeConfiguration()
{
HasMany(x => x.ClassSessions)
.WithOptional(x => x.SessionTime)
.WillCascadeOnDelete(false);
HasMany(x => x.SessionAttendance)
.WithOptional(x => x.Session)
.WillCascadeOnDelete(false);
}
}
public class StudentAttendanceConfiguration : EntityTypeConfiguration<StudentAttendance>
{
public StudentAttendanceConfiguration()
{
HasMany(x => x.SessionAttendances)
.WithRequired()
.WillCascadeOnDelete();
}
}
public class ClassSessionConfiguration : EntityTypeConfiguration<ClassSession>
{
public ClassSessionConfiguration()
{
HasRequired(x => x.EducationDay)
.WithMany(x => x.Sessions)
.WillCascadeOnDelete(true);
HasOptional(x => x.SessionTime)
.WithMany(x => x.ClassSessions)
.WillCascadeOnDelete(false);
}
}
public class CurriculumConfiguration : EntityTypeConfiguration<Curriculum>
{
public CurriculumConfiguration()
{
HasRequired(x => x.Course)
.WithOptional(x => x.Curriculum);
}
}
When I want to delete a Course object, at first I load all the children and mark them as Deleted, and at the end remove that course from the context.
Something like this:
if (course.StudentAttendances.IsNullOrEmpty())
context.Entry(course).Collection(x => x.StudentAttendances);
// Load other children
// Mark list children as deleted
if (!course.Curriculum.Sessions.IsNullOrEmpty())
{
for (int i = course.Curriculum.Sessions.Count - 1; i >= 0; i--)
{
var session = course.Curriculum.Sessions[i];
context.Entry(session).State = EntityState.Deleted;
}
}
// Remove course
context.Courses.Remove(course);
The delete operation ends with an error related to SessionTime's foreign key to the SessionAttendance class.
The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.SessionAttendances_dbo.SessionTime_Session_Id". The conflict occurred in database "MyDb", table "dbo.SessionAttendances", column 'Session_Id
Since the SessionAttendance has a optional SessionTime, I'm confused.
What's the problem? Thanks
The problem is you have to delete associated records in the foreign key tables first before removing the record.
From the logic you were writing, you need to add business scenarios to remove SessionAttendances rows that contain the Session_Id before removing the Session record.
I created my application based on the Identity Framework, and create an interface ApplicationUser to set the User_ID type to GUID. All it's ok, but when I try to load the user using the UserManager class, I get an exception that I cannot understand. I cannot understand why this column is added in the command
The exception:
ORA-00904: "Extent1"."ApplicationUser_Id": identificador inválido
The command that causes the exception:
SELECT
"Extent1"."ID_USER_CLAIM" AS "ID_USER_CLAIM",
"Extent1"."ID_USER" AS "ID_USER",
"Extent1"."CLAIM_TYPE" AS "CLAIM_TYPE",
"Extent1"."CLAIM_VALUE" AS "CLAIM_VALUE",
"Extent1"."ApplicationUser_Id" AS "ApplicationUser_Id"
FROM
"BEECORE"."ADM_USER_CLAIM" "Extent1"
WHERE
("Extent1"."ID_USER" = :p__linq__0)
The code:
var user = userService.UserManager.FindByName(model.UserName);
ApplicationUser:
using Microsoft.AspNet.Identity.EntityFramework;
using System;
namespace Bee.Core.Domain.Identity
{
public class ApplicationUser : IdentityUser<Guid, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public ApplicationUser()
{
Id = Guid.NewGuid();
}
public ApplicationUser(string name) : this() { UserName = name; }
}
}
Configuration:
using Bee.Core.Domain.Identity;
using System.Data.Entity.ModelConfiguration;
namespace Bee.Core.Administration.Data.EntityConfig.Identity
{
public class IdentityUserConfiguration : EntityTypeConfiguration<ApplicationUser>
{
public IdentityUserConfiguration()
{
ToTable("ADM_USER");
HasKey(c => new
{
c.Id
});
Property(c => c.Id).HasColumnName("ID_USER");
Property(c => c.Email).HasColumnName("EMAIL");
Property(c => c.EmailConfirmed).HasColumnName("EMAIL_CONFIRMED");
Property(c => c.PasswordHash).HasColumnName("PASSWORD_HASH");
Property(c => c.SecurityStamp).HasColumnName("SECURITY_STAMP");
Property(c => c.PhoneNumber).HasColumnName("PHONE_NUMBER");
Property(c => c.PhoneNumberConfirmed).HasColumnName("PHONE_NUMBER_CONFIRMED");
Property(c => c.TwoFactorEnabled).HasColumnName("TWO_FACTOR_ENABLED");
Property(c => c.LockoutEndDateUtc).HasColumnName("LOCKOUT_ENDDATEUTC");
Property(c => c.LockoutEnabled).HasColumnName("LOCKOUT_ENABLED");
Property(c => c.AccessFailedCount).HasColumnName("ACCESS_FAILED_COUNT");
Property(c => c.UserName).HasColumnName("USER_NAME");
}
}
}
I had the same problem when I have implemented custom Microsoft Identity. In that case, I needed to configure all foreign keys explicitly in EntityTypeConfiguration for each Identity class/table.
For example, your code need into class User (inherit - IdentityUser):
HasMany(x => x.Claims)
.WithRequired(y => y.ApplicationUser);
HasMany(x => x.Roles)
.WithRequired(y => y.ApplicationUser);
HasMany(x => x.Logins)
.WithRequired(y => y.ApplicationUser);
You need configure all the class Microsoft Identity with Foreign Key:
Class UserClaim (inherit - IdentityUserClaim):
HasRequired(x => x.ApplicationUser)
.WithMany(y => y.Claims)
.HasForeignKey(f => f.UserId);
Class Role (inherit - IdentityRole):
HasMany(c => c.Users).WithRequired().HasForeignKey(c => c.RoleId);
Class UserLogin (inherit - IdentityUserLogin):
HasRequired(x => x.ApplicationUser)
.WithMany(y => y.Logins)
.HasForeignKey(f => f.UserId);
Class UserRole (inherit - IdentityUserRole):
HasRequired(x => x.ApplicationUser)
.WithMany(y => y.Roles)
.HasForeignKey(f => f.UserId);
I hope have help you.
I'm trying to create an ASP.NET Identity DbContext from scratch (getting rid of the depedency on IdentityDbContext<...>)
Nearly there...but my EF Code First fluent relationships are not yet right.
Table structure should come out as:
but getting more like the following:
That's even after I defined the HasForeignKey explicitly.
My question is...where did I go wrong on the relationships?
Thanks!
The mapping I'm using is the following:
public class ApplicationDbContext : DbContext
{
...
public ApplicationDbContext()
: base("DefaultConnection") //, throwIfV1Schema: false
{
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
...
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new IdentityRoleMap());
modelBuilder.Configurations.Add(new IdentityUserClaimMap());
modelBuilder.Configurations.Add(new IdentityUserLoginMap());
modelBuilder.Configurations.Add(new IdentityUserMap());
modelBuilder.Configurations.Add(new IdentityUserRoleMap());
}
...
}
public class IdentityUserClaimMap : EntityTypeConfiguration<IdentityUserClaim>
{
public IdentityUserClaimMap()
{
this.HasKey(t => t.Id);
this.Property(t => t.UserId).IsRequired().HasMaxLength(128);
this.ToTable("Custom_UserClaims");
}
}
public class IdentityUserLoginMap : EntityTypeConfiguration<IdentityUserLogin>
{
public IdentityUserLoginMap()
{
this.HasKey(t => new { t.UserId, t.LoginProvider, t.ProviderKey });
this.Property(t => t.LoginProvider).IsRequired().HasMaxLength(128);
this.Property(t => t.ProviderKey).IsRequired().HasMaxLength(128);
this.Property(t => t.UserId).IsRequired().HasMaxLength(128);
this.ToTable("Custom_UserLogins");
}
}
public class IdentityRoleMap : EntityTypeConfiguration<IdentityRole>
{
public IdentityRoleMap()
{
this.HasKey(t => t.Id);
this.Property(t => t.Id).IsRequired().HasMaxLength(128);
this.Property(t => t.Name).IsRequired().HasMaxLength(256);
this.ToTable("Custom_Roles");
this
.HasMany(x => x.Users)
.WithOptional()
.HasForeignKey(x => x.RoleId);
}
}
public class IdentityUserMap : EntityTypeConfiguration<ApplicationUser>
{
public IdentityUserMap()
{
this.HasKey(t => t.Id);
this.Property(t => t.Id).IsRequired().HasMaxLength(128);
this.Property(t => t.Email).HasMaxLength(256);
this.Property(t => t.UserName).IsRequired().HasMaxLength(256);
this.ToTable("Custom_Users");
//Nav:Claims: User can have 1-(0-*) claims
this
.HasMany<IdentityUserClaim>(x => x.Claims)
.WithRequired()
.HasForeignKey(x => x.UserId)
.WillCascadeOnDelete();
//Nav:Logins: User can have 1-(0-*) Logins
this
.HasMany<IdentityUserLogin>( x => x.Logins)
.WithRequired()
.HasForeignKey(x => x.UserId)
.WillCascadeOnDelete();
//Nav:Roles:
//Interestingly, appears not to be using a *-* Map statement:
this
.HasMany<IdentityUserRole>(x => x.Roles)
.WithRequired()
.HasForeignKey(x => x.UserId)
.WillCascadeOnDelete(false);
}
}
public class IdentityUserRoleMap : EntityTypeConfiguration<IdentityUserRole>
{
public IdentityUserRoleMap()
{
this
.ToTable("Custom_UserRoles")
.HasKey(x => new {x.UserId, x.RoleId});
}
}
Oh, that's annoying.
Turns out that it works fine.
I don't use Sql Server's diagramming tool all that much, and didn't realise that at some point I got it right... but the diagrams kept on being wrong, simply because I didn't Refresh the tables before i selected them. What a waste of time!
Regarding whether to use one or two DbContexts as Erik suggested in the comments, I'll consider it further. For now, I'll play around with using a single DbContext, as all functionality seems to be working fine.
Night.
I know this will probably sound like a vague issue but I don't have a good handle yet on what is happening. Here's what I know:
I am using Breeze 1.4.2 with EF 5.
I have a sporadic issue while calling the Metadata HTTP Get for a specific controller. This controller is a POCO controller built using a code-first DbContext.
The only way I am able to get rid of this problem is by recycling IIs App pools on my 2 nodes load balanced environment. By the way, that only happens in Release mode on the target environment, I have never reproduced this bug locally.
Here's the MetaData method:
[HttpGet]
public override string Metadata()
{
return new EFContextProvider<PersonalizationdDtoContext>().Metadata();
}
Here's the context + configuration:
internal class PersonalizationdDtoContext : DbContext
{
static PersonalizationdDtoContext()
{
// Prevent attempt to initialize a database for this context
Database.SetInitializer<PersonalizationdDtoContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ApplicationDefaultsConfiguration());
modelBuilder.Configurations.Add(new JsDataTableConfiguration());
modelBuilder.Configurations.Add(new MobilePreferenceModelConfiguration());
}
public DbSet<MobilePreferenceModel> MobilePreferenceModel { get; set; }
public DbSet<ApplicationDefaults> ApplicationDefaults { get; set; }
public DbSet<JsDatatable> JsDatatables { get; set; }
}
internal class ApplicationDefaultsConfiguration : EntityTypeConfiguration<ApplicationDefaults>
{
public ApplicationDefaultsConfiguration()
{
this.HasKey(c => c.Id);
this.Property(c => c.LastUpdateDateTime).IsConcurrencyToken();
this.Property(c => c.PreferenceTypeId).IsRequired();
this.Property(c => c.Id).IsRequired();
}
}
internal class JsDataTableConfiguration : EntityTypeConfiguration<JsDatatable>
{
public JsDataTableConfiguration()
{
this.HasKey(c => c.Id);
this.Property(c => c.LastUpdateDateTime).IsConcurrencyToken();
this.Property(c => c.PreferenceTypeId).IsRequired();
this.Property(c => c.Id).IsRequired();
this.HasRequired(p => p.MobilePreferenceModel)
.WithMany(p => p.JsDatatables)
.HasForeignKey(q => q.MobilePreferenceModelID);
}
}
internal class MobilePreferenceModelConfiguration : EntityTypeConfiguration<MobilePreferenceModel>
{
public MobilePreferenceModelConfiguration()
{
this.HasKey(c => c.Id);
this.HasOptional(p => p.ApplicationDefaults)
.WithRequired();
}
}
I am going to try to upgrade to latest breeze assemblies on the server to see if I can get passed this issue.
Any idea of what might be happening?
I want to create a mapping class similar to the one mentioned below. I want to convert this Fluent NHibernate mapping class to Entity Framework.
Fluent NHibernate
using FluentNHibernate.Mapping;
using MyBlog.Core.Objects;
public class PostMap: ClassMap<Post>
{
public PostMap()
{
Id(x => x.Id);
Map(x => x.Title)
.Length(500)
.Not.Nullable();
Map(x => x.ShortDescription)
.Length(5000)
.Not.Nullable();
Map(x => x.Description)
.Length(5000)
.Not.Nullable();
Map(x => x.Meta)
.Length(1000)
.Not.Nullable();
Map(x => x.UrlSlug)
.Length(200)
.Not.Nullable();
Map(x => x.Published)
.Not.Nullable();
Map(x => x.PostedOn)
.Not.Nullable();
Map(x => x.Modified);
References(x => x.Category)
.Column("Category")
.Not.Nullable();
HasManyToMany(x => x.Tags)
.Table("PostTagMap");
}
}
Is NHibernate support available with Hosting Services? Is it easily available with any ASP.NET Hosting or only selected services use it?
Yes, Entity Framework has the similar mappings.
NHibernate:
public PostMap()
{
Map(x => x.Title)
.Length(500)
.Not.Nullable();
}
Entity Framework:
public class YourDomainModelContext : DbContext
{
public YourDomainModelContext() { }
...
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Post>()
.Property(u => u.Title)
.HasMaxLength(500);
}
}
You can get more information in these blog-posts:
Configuring/Mapping Properties and Types with the Fluent API
Entity Framework Mapping Scenarios
Fluent API vs Data Annotations
For EF4 and EF5 there are Fluent API generators, but for EF6 not. I'm also searching for one that works.