The new version of ASPNET Entity Framework 7.0.0-beta3 has changed and I can't find OneToMany.
In the previous version this would work.
#region Table setup
public DbSet<User> Users { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<UserCompany> UserComanies { get; set; }
#endregion
#region Setup DbContext
/// <summary>
/// Build data model in here.
/// </summary>
/// <param name="builder">Builder.</param>
protected override void OnModelCreating(ModelBuilder builder) {
builder.Entity<User>().OneToMany(c => c.UserCompanies, uc => uc.User).ForeignKey(uc => uc.UserId).Required(true);
}
Does anyone know what to do in beta3?
Help would be appreciated.
It is now HasMany, as documented on the Wiki https://github.com/aspnet/EntityFramework/wiki/Using-EF7-in-Traditional-.NET-Applications
Related
I know my question is kinda broad but I haven't found any good answers online.
I am building an ASP.NET Core MVC web app. I am looking for tips on how to bind a specific user to entities (classes in model). The problem is really about how to bind a certain user to a certain entity in the database.
Any help would be greatly appreciated.
ApplicationUser (or IdentityUser) is like any other entity class.
Creating a 1-n relationship, for example, would look something like:
public class ApplicationUser : IdentityUser
{
public virtual IList<MyEntity> MyEntities { get; set; } // navigation property
}
public class MyEntity
{
public int Id { get; set; }
public string CreatedByUserId { get; set; } // FK
public ApplicationUser CreatedByUser { get; set; } // Navigation property
}
You could also do this the fluent way:
public class ApplicationUser : IdentityUser { }
public class MyEntity
{
public int Id { get; set; }
public string CreatedByUserId { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<MyEntity>(b => {
b.HasOne<ApplicationUser>()
.WithMany()
.HasForeignKey(myEntity => myEntity.CreatedByUser);
});
}
}
Entity Framework Core DbSet is not returning any data from database, but the database has many register.
This is the entity
public class Entity : BaseEntity
{
public int EntityStatusId { get; set; }
public int AddressId { get; set; }
public string Name { get; set; }
public string SocialReason { get; set; }
public string CNPJ { get; set; }
public EntityType Type { get; set; }
public DateTime? CreationDate { get; set; }
public bool? ReceiptDisabled { get; set; }
public EntityStatus EntityStatus { get; set; }
public Address Address { get; set; }
public List<Company> Companies { get; set; }
public List<Role> RoleList { get; set; }
}
public abstract class BaseEntity
{
public int Id { get; set; }
}
Now this is the configuration class.
public class EntityMap : IEntityTypeConfiguration<Entity>
{
public void Configure(EntityTypeBuilder<Entity> builder)
{
builder.ToTable("Entity");
builder.HasKey(entity => entity.Id);
builder
.Property(entity => entity.EntityStatusId);
builder
.Property(entity => entity.AddressId);
builder
.Property(entity => entity.Name);
builder
.Property(entity => entity.SocialReason);
builder
.Property(entity => entity.CNPJ);
builder
.Property(entity => entity.Type)
.HasConversion(x => (int)x, x => (EntityType)x);
builder
.Property(entity => entity.CreationDate);
builder
.Property(entity => entity.ReceiptDisabled);
builder
.HasOne(entity => entity.EntityStatus);
builder
.HasOne(entity => entity.Address);
builder
.HasMany(entity => entity.RoleList)
.WithOne(x => x.Entity);
builder
.HasMany(entity => entity.Companies)
.WithOne(x => x.Entity);
}
}
And the context class.
public class AucContext : DbContext
{
public AucContext(string databaseConfiguration)
{
_databaseConfiguration = databaseConfiguration;
}
private readonly string _databaseConfiguration;
public DbSet<Campaign> Campaigns { get; set; }
public DbSet<CampaignProject> CampaignProjects { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<Cart> Carts { get; set; }
public DbSet<CartItem> CartItems { get; set; }
public DbSet<Donation> Donations { get; set; }
public DbSet<DonationRecurrencePeriod> DonationRecurrencePeriods { get; set; }
public DbSet<Entity> Entities { get; set; }
public DbSet<Institution> Institutions { get; set; }
public DbSet<PaymentMethod> PaymentMethods { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CampaignMap());
modelBuilder.ApplyConfiguration(new CampaignProjectMap());
modelBuilder.ApplyConfiguration(new CompanyMap());
modelBuilder.ApplyConfiguration(new CartMap());
modelBuilder.ApplyConfiguration(new CartItemMap());
modelBuilder.ApplyConfiguration(new DonationMap());
modelBuilder.ApplyConfiguration(new DonationRecurrencePeriodMap());
modelBuilder.ApplyConfiguration(new EntityMap());
modelBuilder.ApplyConfiguration(new InstitutionMap());
modelBuilder.ApplyConfiguration(new PaymentMethodMap());
modelBuilder.ApplyConfiguration(new PersonMap());
modelBuilder.ApplyConfiguration(new ProjectMap());
modelBuilder.ApplyConfiguration(new UserMap());
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_databaseConfiguration);
}
}
And the query was simple
var entity = context.Entities.Find(3)
this simple query is returning nothing, any ideas for what is happening?
Update
I have updated somethings since yesterday, and now i have updated the question unfortunately still don't work
OBS:. The ConnectionString it's ok, other objects just work fine.
First, add Id to your Entity:
public int Id { get; set; }
Then in your DbContext:
1:In your OnModelCreating,add
modelBuilder.ApplyConfiguration(new EntityMap());
2:Add DbSet:
public DbSet<Entity> Entity { get; set; }
Re-migrate and update the database.Your code will work fine.
An interesting problem if some entities work but this one doesn't. There are a couple additional things to check/try:
Ensure you have no duplicate mappings. For example, if your Entity has a HasMany.WithOne relationship with another entity, ensure that the mapping for that other entity does not declare a HasOne.WithMany or other relationship back to Entity. This can cause weird behaviour.
Your HasOne relationships are missing WithMany and FK declarations. Given you are using "Id" as a base inherited PK on your entities you should consider explicitly declaring your FK relationships. The WithMany declaration is optional in EFCore, however it is needed to declare the FK if it doesn't follow convention. (and I'm no fan of convention for just deciding not to work)
builder
.HasOne(entity => entity.EntityStatus)
.WIthMany()
.HasForeignKey(entity => entity.EntityStatusId);
builder
.HasOne(entity => entity.Address);
.WIthMany()
.HasForeignKey(entity => entity.AddressId);
EF should be working out the FK names by convention though. Just keep in mind that EF conventions follow the type name, not property name so for instance something like this:
public User CreatedBy { get; set; }
by convention would be looking for a FK property of UserId rather than CreatedById which can lead to weird behaviour or errors.
On a side note you do not need to declare .Property() for each property in an entity, only for properties that require some special configuration like IdentityColumn, NotMapped (ignore) or specifying a data constraint / length etc. I would also recommend removing the .Property() statement for any FK columns in your entity
This all said, I've tinkered with a test EF Core project setting up duplicate mapping between objects and leaving off WithMany() and FK declarations and I was not able to reproduce your issue. I think there is something very specific to your schema or mapping that is tripping up EF to resolve this "Entity" object. If these changes do not work, take it down to the minimum viable object and remove all related entity mappings, setting them all to NotMapped so-as not to break your code and then try loading your Entity objects. From there re-introduce the relationships one by one until it stops loading them and narrow it down. If you do identify a rogue mapping responsible, do be sure to post an update with details about the culprit because it would probably be useful in case someone else gets tripped up by it.
I've created a table that has a relation with itself the table has a one-to-many relationship here is my Entity:
public class Permission
{
[Key]
public int PermissionId { get; set; }
public string PermissionTitle { get; set; }
public int? ParentId { get; set; }
#region Relations
[ForeignKey("ParentId")]
public virtual ICollection<Permission> Permissions { get; set; }
#endregion
}
but when I used migration to create the table in SQL, update-database failed for this error:
Introducing FOREIGN KEY constraint 'FK_Permission_Permission_ParentId' on table 'Permission' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
So I decided to use fluent API to solve this issue but I don't know how to Specify ON DELETE NO ACTION by Fluent API on a table that has a relation with itself. any help?
is there any solution to solve my problem?
For EF Core the Entity should normally have two Navigation Properties, like this:
public class Permission
{
[Key]
public int PermissionId { get; set; }
public string PermissionTitle { get; set; }
public int? ParentPermissionId { get; set; }
#region Relationships
public virtual Permission ParentPermission { get; set; }
public virtual ICollection<Permission> ChildPermissions { get; } = new HashSet<Permission>();
#endregion
}
And configured like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Permission>()
.HasMany(p => p.ChildPermissions)
.WithOne(p => p.ParentPermission)
.HasForeignKey(p => p.ParentPermissionId)
.OnDelete(DeleteBehavior.Restrict);
base.OnModelCreating(modelBuilder);
}
I have a MVC4 Web api project under visual studio 2012 for which I would like to create and manage database using EF 6.0.2 code first. Actually, the solution entails four projects, namely,
OnlineShop.Application (User interface)
OnlineShop.Model dedicated to POCO classes only
OnlineShop.Test for unit tests and
OnlineShop.Core having UnitOfWork, GenericRepository and
DatabaseContext classes
Each of the mentioned projects includes an app.config which holds Same connection as that of web.config.
Problem: After running the project (in debug mode), the database is created as it's shown on server explorer (in visual studio 2012). But, it has no tables!!!
The database context class is also as the following:
public class DatabaseContext : DbContext
{
public DatabaseContext() : base("OnlineShopDb")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DatabaseContext, Configuration>());
}
//public static void InitializeDatabase()
//{
// using (var context = new DatabaseContext())
// {
// context.Database.CreateIfNotExists();
// Database.SetInitializer(new MigrateDatabaseToLatestVersion<DatabaseContext, Configuration>());
// }
//}
public DbSet<Person> Persons { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Audit> Audits { get; set; }
public DbSet<RoleGroup> RoleGroups { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<UserInRole> UserInRoles { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<ProductCategory> ProductCategories { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<Person>().Map<User>(c => c.Requires("Discriminator").HasValue("User"));
}
}
I have surfed the web so much, found lots of articles ans samples regarding EF code first approach but unfortunately couldn't handle this bad problem!
I would appreciate it if anyone could help me on this.
Entity Framework code first does not create your database until you try to access it, so run your project and try to get or insert some record to your database.
another usefull tip is that if you change your models EF by default will throw an exeption, and you will have to drop the current database so EF can crate a new one.
or I recomend you to change that default behavior this way
Im using mvc5 with codefirst and the user account stuff.
I have a simple requirement a user can belong to multiple stores and a business can have multiple stores.
So far I have the business - many stores working but I cant seem to figure out how to setup the users.
My StoreModel
public virtual Business Business { get; set; }
public virtual ICollection<ApplicationUser> Employees { get; set; }
My BusinessModel
public virtual ICollection<StoreModel> Stores { get; set; }
Within my context I have tried
public class ApplicationUser : IdentityUser
{
//a user can belong to multiple stores
public virtual ICollection<StoreModel> Stores { get; set; }
}
however when I try add-migration the code generated is going to change my table names and does create the join table between Store & AspNetUser
My migration looks like
public override void Up()
{
RenameTable(name: "dbo.Stores", newName: "ApplicationUserStoreModels");
DropForeignKey("dbo.Stores", "ApplicationUser_Id", "dbo.AspNetUsers");
DropIndex("dbo.Stores", new[] { "ApplicationUser_Id" });
CreateIndex("dbo.ApplicationUserStoreModels", "ApplicationUser_Id");
CreateIndex("dbo.ApplicationUserStoreModels", "StoreModel_StoreId");
AddForeignKey("dbo.ApplicationUserStoreModels", "ApplicationUser_Id", "dbo.AspNetUsers", "Id", cascadeDelete: true);
AddForeignKey("dbo.ApplicationUserStoreModels", "StoreModel_StoreId", "dbo.Stores", "StoreId", cascadeDelete: true);
DropColumn("dbo.Stores", "ApplicationUser_Id");
}
Can anyone help what I need to do to get this working?
you can either just not have a store table and put a list in each appuser and business and EF will make your many to many relationship or you can use fluent api to map everything. Should be something like the following.
public class Business
{
public virtual ICollection<StoreModel> Stores { get; set; }
}
public class ApplicationUser : IdentityUser
{
public virtual ICollection<StoreModel> Stores { get; set; }
}
public class StoreModel {
public string ApplicationUserId { get; set; }
public int BusinessId { get; set; }
public virtual Business Businesss { get; set; }
public virtual ApplicationUser ApplicationUsers { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ base.OnModelCreating(modelBuilder);
modelBuilder.Entity<StoreModel>().HasKey(e => new { e.ApplicationUserId, e.BusinessId});
}