is there any way to share a table in database with multiple context of EF ?
I want to define many models (code first) and bind theme to a single table in a database like this:
public class Context1 : DbContext
{
[Table("Post")]
public DbSet<Post1> Posts { get; set; }
}
public class Context2 : DbContext
{
[Table("Post")]
public DbSet<Post2> Posts { get; set; }
}
public class Context3 : DbContext
{
[Table("Post")]
public DbSet<Post3> Posts { get; set; }
}
all post models are inherited from a basePost for example.
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);
});
}
}
Is it possible to inherit a custom DBContext and then modify the entities of the inherited context has without modifying the base tables with discriminator columns?
public class BaseDbContext: DbContext {
public IDbSet<BaseClass> BaseClasses { get; set; }
}
public class BaseClass {
public int Id { get; set; }
etc...
}
public class NewDbContext: BaseDbContext {
public IDbSet<NewBaseClass> NewBaseClasses { get; set; }
}
public class NewBaseClass: BaseClass {
public string SomePropertyName { get; set; }
}
I have a project that is setup for a base database structure use the BaseDbContext. If I created a new database with the same schema and added a column to the BaseClasses table called SomePropertyName. I want to create a new DbContext that derives from the BaseDbContext, and then add the extra property to the new class, NewBaseClass.
Any guidance would be greatly appreciated.
I'm trying to make a relationship between the Users from the table generated by Asp.Net Identity with my own table. The relationship must be many to many, since many Users can work on the same Task (which is my table), and same time an User can work on multiple Tasks.
public class Task
{
public int ID { get; set; }
public string Name { get; set; }
public string UserID { get; set; }
public virtual ICollection<ApplicationUser> Users { get; set; }
}
public class ApplicationUser : IdentityUser
{
public int TaskID { get; set; }
public virtual ICollection<Task> Tasks{ get; set; }
// rest of the code
}
I try it this way but I get an error during migration (or run time)
"One or more validation errors were detected during model generation:"
Please help me solve this problem and archive what I need.
Try it like this:
public class Projects
{
public Projects()
{
ApplicationUser = new HashSet<ApplicationUser>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
Application User
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
Projects = new HashSet<Projects>();
}
public async Task GenerateUserIdentityAsync(UserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public virtual ICollection <Projects > Projects { get; set; }
}
Application Context :
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public virtual DbSet<Projects> Projects { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
now when I run this Mvc app and register, the db tables I get is like the following:
and the correct schema:
The things to be questioned are a lot, from my point of view important is to determine if you:
- can/should you mix application context and your model context ?
You can try it as shown below using Fluent API.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Task>()
.HasMany<ApplicationUser>(s => s.Users)
.WithMany(c => c.Tasks)
.Map(cs =>
{
cs.MapLeftKey("TaskRefId");
cs.MapRightKey("ApplicationUserRefId");
cs.ToTable("TaskApplicationUser");
});
}
Update : you can see this link too.
EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType
Error text is not related to your many-to-many relationship. It tips that other built-in entities are not configured properly. So, It would be nice if you provided full definition of your custom DbContext-class and how it is configured.
UPDATE
As i understood u are working with two different contexts. You must work with the same context, cause of u are extending IdentityContext, creating relationships and adding custom types. So problem then will be resolved itself.
Hope, this will help.
I have two DbContext class and some Entities in them. I know this is not good idea to have more than one DbContext but i have to do a lot of works to change my code! so my question is what is the best scenario for add relationship between two Entities with different DbContext?
For example an one to many relationship between User Entity with IdentityDb Context and Comment Entity with SiteDbContext :
public class User : IdentityUser
{
public DateTime JoinDate { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this,DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
public class IdentityDb : IdentityDbContext<ApplicationUser>
{
public IdentityDb() : base("DefaultConnection", throwIfV1Schema: false)
{
}
public static IdentityDb Create()
{
return new IdentityDb();
}
}
public class Comment
{
public int CommentId { get; set; }
[Required]
[StringLength(900)]
public string CommentText { get; set; }
[DataType(DataType.Date)]
public DateTime CommentDate { get; set; }
}
public class SiteDb: DbContext
{
public SiteDb(): base("DefaultConnection")
{
}
public DbSet<Comment> Comments{ get; set; }
}
Short answer: Entity Framework currently doesn't support creating a query which uses more than one context.
For work around: Refer this.
I have an existing model with multiple levels of inheritence with several of the intermediate classes being abstract. The model looks fine, but when trying to create the database I get the error:
Problem in mapping fragments starting at lines 13, 20:Two entities with different keys are mapped to the same row. Ensure these two mapping fragments do not map two groups of entities with different keys to the same group of rows.
Here's the simplest code I could write to reproduce the error. If I make Pet concrete, the problem goes away. What I can I do to allow multiple abstract classes in my hierarchy?
public abstract class Animal
{
public int Id { get; set; }
}
public abstract class Pet : Animal
{
public string Name { get; set; }
}
public class Fish : Pet
{
public bool IsFreshwater { get; set; }
}
public class Dog : Pet
{
public bool IsNeutered { get; set; }
}
public class Person : Animal
{
public Pet MyPet { get; set; }
}
public class PersonContext : DbContext
{
public DbSet<Person> People { get; set; }
}
[TestFixture]
public class AnimalTests
{
[Test]
public void CanCreateDatabase()
{
Database.SetInitializer(new DropCreateDatabaseAlways<PersonContext>());
using (var context = new PersonContext())
{
Assert.AreEqual(0, context.People.Count());//fails here
}
}
}
Update. Here's a KDiff snap of the differences in the generated .edmx file. The file on the left is my original code that fails and on the right is what is generated when I include a DbSet<Pet> in my DbContext.
You need to add Pets to your context:
// Table-per-class (TPC)
public class PersonContext : DbContext
{
public PersonContext()
{
}
public DbSet<Person> People { get; set; }
public DbSet<Pet> Pets { get; set; }
}
Edit: I just saw your comment where you stated you wanted table by hierarchy inheritance. Your problem, then, is that your DbSet is not typed properly - you want a single DbSet using the base type:
// Table-per-hierarchy (TPH)
public class PersonContext : DbContext
{
public PersonContext()
{
}
public DbSet<Animal> Animals { get; set; }
}