I'm designing a multi tenant website using EF6 code first, MVC, and other from the MS stack.
I want to have announcements for each Tenant. Simple enough, my EF code first class would look something like this:
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public virtual Tenant Tenant { get; set; }
public ApplicationUser Author { get; set; }
}
My design question is what if I want the site administrator to have the ability to post announcements to all tenants?
Since the database will force the Tenant relationship, I can't set the Tenant property to something artificial.
Before EF, I'd do something like this, but now I will lose the nice-to-have EF Navigation property.
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public string Title { get; set; }
public string Message { get; set; }
public int TenantID { get; set; }
public ApplicationUser Author { get; set; }
}
I would use TenantID appropriately for all Tenant based announcements, but would set it to 0 for site wide announcements.
So, is there a better design (other than two classes/tables) that can still leverage the EF Navigation properties?
What is the issue with
class Announcement
{
public Announcement()
{
DateCreated = DateTime.Now;
}
[Key]
public virtual int Id { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual string Title { get; set; }
public virtual string Message { get; set; }
public virtual int TenantID { get; set; } // during insert/Update set as required. the tenant should exist.
// A dummy SYSTEM wide tenant may be an option to consider
// navigation props
[ForeignKey("TenantID")]
public virtual Tenant Tenant { get; set; } // <<<<< NAV as before
public virtual ApplicationUser Author { get; set; }
}
Related
I Got This Issue:
I Have the Application User Class Like This
public class ApplicationUser : IdentityUser
{
public ROLES Role { get; set; }
public int? CompanyId { get; set; }
public int? AreaId { get; set; }
public string Document { get; set; }
public bool Enable { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[ForeignKey("AreaId")]
public virtual Area Area { get; set; }
public virtual ICollection Measures { get; set; }
}
And I Got this another Model:
public class Area
{
public int AreaId { get; set; }
public string AreaName { get; set; }
public int CompanyId { get; set; }
public string UserId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Key, ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
}
And when i try to:
add-migration
the PM Console throws:
Unable to determine the principal end of an association between the types 'x.Models.ApplicationUser' and 'x.Models.Area'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I have been trying all day but I can't find a way to tell the Entity Framework to recognize the relation.
Any ideas?
Thanks for reading
Add Attribute for AreaId in Area class
[Key]
public int AreaId { get; set; }
and if you want 1-1 relationship for ApplicationUser and Area update your code like
[Unique]
[ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations
This Post give me the Answer I Need!!!
It's pretty hard to find...
So I let you the post here...
Thanks for all of your help!
I'm trying to create my database from my models, but I keep getting the error Introducing FOREIGN KEY constraint 'FK_dbo.Reports_dbo.UserProfiles_UserId' on table 'Reports' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
anyone knows what might be wrong with my models/setup?
These are all used Models
public class Report {
[Key]
public int Id { get; set; }
[Required]
public string Number { get; set; }
public bool Synced { get; set; }
public DateTime CreationDate { get; set; }
public int NewCommentId { get; set; }
public virtual Comment NewComment { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Photo> PhotosBefore { get; set; }
public virtual ICollection<Photo> PhotosAfter { get; set; }
}
public class Photo {
[Key]
public int Id { get; set; }
public string Image { get; set; }
public bool Synced { get; set; }
public DateTime CreationDate { get; set; }
public int ReportId { get; set; }
public virtual Report Report { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
}
public class Comment {
[Key]
public int Id { get; set; }
public DateTime CreationDate { get; set; }
public string Text { get; set; }
public int ReportId { get; set; }
public virtual Report Report { get; set; }
public int UserId { get; set; }
public virtual UserProfile User { get; set; }
}
public class UserProfile {
[Key]
public int Id { get; set; }
public string Stamnummer { get; set; }
public string Leverancier { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Report> Reports { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
In order to be certain, we need to see how you have configured your relationships using the model builder in the OnModelCreating method. Based on the error message you have provided, it appears that you have relationships configured so that one of your entities is configured for cascade on delete from two or more other entities.
As an example (this may not be the case, but rather just a means of describing the problem):
User has a one-to-many relationship with Comments
User has a one-to-many relationship with Reports
Report has a one-to-many relationship with Comments
Comment is configured so that a User is required
Comment is configured so that a Report is required
Report is configured so that a User is required
Any one-to-many relationship where the entity one side of the relationship is required is going to have cascade on delete configured by default. In this scenario, if a User were deleted it would trigger a cascade to both Reports and Comments. Each Report would also cause a cascade on Comments.
The solution is to disable cascading deletes for one of the relationships. You can find a similar question to yours here describing what I mentioned above.
For example we have profile and organisation. Both have articles.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Email { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Organisation
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
In this way Article should have two kinds of parent so it should have something like parent type to be able to access a parent when you select articles directly.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
What is the best practice for storing this kind of data?
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
Possible yes but not a good idea. The underlying Database can't use a foreign key for Parentid. It would be slow.
What is the best practice for storing this kind of data?
A simple approach, with 2 Nullable parents and without CascadeOnDelete:
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Profile Profile { get; set; }
public virtual Organisation Organisation { get; set; }
}
Alternatively you could use inheritance for Article, ie class OrganisationArticle : Article {}
Hi I am using CodeFirst approach to create database but I am getting below error
The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
The entities are following
public abstract class EntityBase
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public DateTime CreationDate { get; set; }
public DateTime ModifiedDate { get; set; }
public int CreatedByUserId { get; set; }
public int ModifiedByUserId { get; set; }
[ForeignKey("CreatedByUserId")]
public virtual User CreatedBy { get; set; }
[ForeignKey("ModifiedByUserId")]
public virtual User ModifiedBy { get; set; }
public bool IsActive { get; set; }
}
public class User : EntityBase
{
public string UserName { get; set; }
public string DisplayName { get; set; }
public string Password { get; set; }
}
Please help me.
Thanks
Vinod
Right now I'm learning ADO.NET Entity Framework and there's one thing that I can't explain to myself. Here is a source code from a tutorial I've been using recently:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public User UserId { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string DisplayName { get; set; }
}
First I thought that the using of List<> is the way to implement Foreign Key-like behaviour but now knowing that's not the case why we need and for what purpose we use List<> in our entites?
To show that Blog have a lot of Posts, when you will build your project in DB will be the relation 1xBlog--->NxPost where N=unlimited. This will show that each Blog can have unlimited amount of Posts