The problem is that i cannot understand what is the meaning of the Dbset used in it.
Is it a way to initialize a list or is it a part of Entity Framework??
Have you read Microsofts documentation?
"A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type."
An easy way to think about it is that a DbSet represents a table in your database. It is almost always used together with something called a DbContext, which essentially is a representation of a database connection.
Example code that shows how several DbSets are used together with a DbContext:
public class User
{
public string Name { get; set; }
}
public class UserGroup
{
public string Name { get; set; }
public ICollection<User> Users { get; set; }
}
public class ExampleDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
}
Please refer to this tutorial on how to get started with Entity Framework.
Related
I have looked and havent seen anything on this, most information relates to directly extending Identity tables.
I have extended Application User like so:
public class ApplicationUser : IdentityUser<long>
{
//[Key()]
//public long Id { get; set; }
[Required()]
[MaxLength(100)]
public string Password { get; set; }
[Required()]
[MaxLength(100)]
override public string UserName { get; set; }
[Required()]
[MaxLength(50)]
public string FirstName { get; set; }
[Required()]
[MaxLength(50)]
public string LastName { get; set; }
public virtual Organization Organization { get; set; }
}
public class ApplicationRole : IdentityRole<long>
{
}
along with other neccesary changes to ApplicationDbContext (to change the primary key to long). Other than that, its fairly standard Identity stuff. I add migrations, update; the usual tables are created plus Organization table because it's a navigation property. Organization itself has no navigation properties. Keep in mind, for the most part I was handed these classes as part of a project and am trying to work within the confines of what I've been given.
Now, I have several classes that I need to add, one as an example:
public class Event
{
[Key()]
public long Id { get; set; }
[Required()]
[MaxLength(200)]
public string Name { get; set; }
[Index]
public virtual Organization Organization { get; set; }
}
There are a handful of other something inter related classes. So in a standard code first core 2 app with no existing db, I would create the context class that derives from DbContext, whereas in Identity ApplicationDbContext (the default name) derives from IdentityDbContext.
So before I start breaking things, are there any concerns or special considerations before I do something like this?
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
public DbSet<Event> Events{ get; set; }
public DbSet<OtherClass> OtherClasses{ get; set; }
}
Note: I did find this post which seems to do what I am talking about but it is for MVC 5
You can just add the classes as properties, i.e. public DbContext<Class> Classes {get;set;} to the ApplicationDbContext class and you will get data access. They don't need to be related. If you need a sample let me know. Hope this helps.
I'm following this Building a simple ToDo application which is an EF code first model.
This is slightly simplified code from the example that creates two tables, MyUsers and ToDos
public class MyUser : IdentityUser
{
public virtual ICollection<ToDo> ToDoes { get; set; }
}
public class ToDo
{
public int Id { get; set; }
public string Description { get; set; }
public bool IsDone { get; set; }
public virtual MyUser User { get; set; }
}
My question - what is the ICollection in the parent table for?
public virtual ICollection<ToDo> ToDoes { get; set; }
If you take this line out of the code you get the same two tables with the same referential integrity. This is because the ToDo class contains a the reference to the parent
public virtual MyUser User { get; set; }
Either way it works, so why is it included? Most examples of creating referential integrity include the same format.
Thank you.
Without it you won't be able to navigate from a user to his Todo's easily.
With this ICollection<ToDo> you could load the ToDos of a specified MyUser in one DB transaction, if you need. in the other word, you could load one (or more of cource) MyUser with its ToDos during a single statement:
using(var context = new MyDbContext)
{
var firstUserWithItsToDoes = context.MyUsers.Include(t => t.ToDoes).FirstOrDefault();
}
I am getting Error when trying to run this code.
Unable to determine the principal end of an association between the
types 'AddressBook.DAL.Models.User' and 'AddressBook.DAL.Models.User'.
The principal end of this association must be explicitly configured
using either the relationship fluent API or data annotations.
The objective is that i am creating baseClass that has commonfield for all the tables.
IF i don't use base class everything works fine.
namespace AddressBook.DAL.Models
{
public class BaseTable
{
[Required]
public DateTime DateCreated { get; set; }
[Required]
public DateTime DateLastUpdatedOn { get; set; }
[Required]
public virtual int CreatedByUserId { get; set; }
[ForeignKey("CreatedByUserId")]
public virtual User CreatedByUser { get; set; }
[Required]
public virtual int UpdatedByUserId { get; set; }
[ForeignKey("UpdatedByUserId")]
public virtual User UpdatedByUser { get; set; }
[Required]
public RowStatus RowStatus { get; set; }
}
public enum RowStatus
{
NewlyCreated,
Modified,
Deleted
}
}
namespace AddressBook.DAL.Models
{
public class User : BaseTable
{
[Key]
public int UserID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Password { get; set; }
}
}
You need to provide mapping information to EF. The following article describes code-first strategies for different EF entity inheritance models (table-per-type, table-per-hierarchy, etc.). Not all the scenarios are directly what you are doing here, but pay attention to the mapping code because that's what you need to consider (and it's good info in case you want to use inheritance for other scenarios). Note that inheritance does have limitations and costs when it comes to ORMs, particularly with polymorphic associations (which makes the TPC scenario somewhat difficult to manage). http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx
The other way EF can handle this kind of scenario is by aggregating a complex type into a "fake" compositional relationship. In other words, even though your audit fields are part of some transactional entity table, you can split them out into a common complex type which can be associated to any other entity that contains those same fields. The difference here is that you'd actually be encapsulting those fields into another type. So for example, if you moved your audit fields into an "Audit" complext type, you would have something like:
User.Audit.DateCreated
instead of
User.DateCreated
In any case, you still need to provide the appropriate mapping information.
This article here explains how to do this: http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
Let's say I have a model where I have the Person entity with general info (Names, Date of Birth, etc.), and two additional entities (Customer, Worker) which inherit from Person. As you see there is the option of having a Customer who CAN ALSO play the role of a Worker in the model. There is a way to design this in EF (I saw something about TPH, TPT and TPC) but I see that there is a use of discriminator which doesn't allow a Person table to include values for Worker and Customer "simultaneously".
I don't know if maybe I'm getting wrong with the general OOP concept of inheritance :S.
Thanks in advance for all your help.
You cant have multiple inheritance in .net, it is not supported (and the same applies to entity framework). You can implement multiple interfaces, but this is a slightly different notion - i.e. 'Worker' could be an interface that is implemented by some objects, such as customer
In entity framework, I believe that the discriminator is only implemented when using Table-per-hierarchy. This is where both child entities are stored in the same table, and the discriminator identifies which is which.
Table-per-type is essentially where the entities (person, customer, worker) are stored in different tables, but are accessible as single entities in your code (i.e. customer with an inheritance from person)
It may be that you need to create an interface (maybe IWorker), and create a class (maybe WorkerCustomer??) that inherits from Customer, and implements IWorker.
EDIT: 15/02/2013 19:00
Ok, so the below might be what you're looking for in terms of representing the data in a single table:
public class MyDbContext : DbContext
{
public MyDbContext() : base("TestDB")
{
}
public DbSet<Person> People { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Worker> Workers { get; set; }
public DbSet<WorkerCustomer> WorkerCustomers { get; set; }
}
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Customer : Person
{
public string CustomerNumber { get; set; }
}
public interface IWorker
{
string WorkerNumber { get; set; }
}
public class Worker : Person, IWorker
{
public string WorkerNumber { get; set; }
}
public class WorkerCustomer : Customer
{
public string WorkerNumber { get; set; }
}
Spinning further on the previous question I had. Let's say I inherit BlogEntry and Comment from Post. I now want to customize them a bit. A comment to a blog post does not need a title but a comment needs a user reference so I move these two fields out from Post and into Comment and Blog entry like this:
public abstract class Post
{
public virtual int Id { get; set; }
public virtual string Text { get; set; }
public virtual DateTime CreatedAt { get; set; }
}
public class BlogEntry : Post
{
public virtual string Header { get; set; }
public virtual Blog Blog { get; set; }
public virtual IEnumerable<Comment> Comments { get; set; }
}
public class Comment : Post
{
public virtual string Header { get; set; }
public virtual int UserId { get; set; }
public virtual BlogEntry BlogEntry { get; set; }
}
Now I create my custom object context:
public class EntityContext : System.Data.Objects.ObjectContext
{
public EntityContext() : base("name=Entities", "Entities")
{
this.Blogs = CreateObjectSet<Blog>();
this.Posts = CreateObjectSet<Post>();
this.Entries = CreateObjectSet<BlogEntry>();
this.Comments = CreateObjectSet<Comment>();
}
public ObjectSet<Blog> Blogs { get; set; }
public ObjectSet<Post> Posts { get; set; }
public ObjectSet<BlogEntry> Entries { get; set; }
public ObjectSet<Comment> Comments { get; set; }
}
This gives me the following actually quite descriptive error message:
Test method threw exception:
System.ArgumentException: There are
no EntitySets defined for the
specified entity type 'BlogEntry'. If
'BlogEntry' is a derived type, use the
base type instead. For example, you
would see this error if you called
CreateObjectSet()
and DiscontinuedProduct is a known
entity type but is not directly mapped
to an EntitySet. The
DiscontinuedProduct type may be a
derived type where the parent type is
mapped to the EntitySet or the
DiscontinuedProduct type might not be
mapped to an EntitySet at all.
Parameter name: TEntity
Now I am not a master of inheritance and stuff but the way I see this would be to add a set of Entries and Comments as ObjectSet< Post> that would solve my problems?
If you create an ObjectSet for a base type (i.e. Post) you can't create one for derived types too, because you can retrieve instances of all types in the inheritance hierarchy from that one ObjectSet.
i.e. ctx.Posts.OfType<BlogEntry>() would return BlogEntry(s).
So the answer is to simply remove the other two sets.
If yo need to do an add for example you can do this:
ctx.Posts.AddObject(new BlogEntry {....});
no problem at all.
To help you write queries more easily you could probably add a couple of properties to your ObjectContext that look like this:
public ObjectQuery<BlogEntity> Blogs{
get{
return ctx.Posts.OfType<BlogEntry>() as ObjectQuery<BlogEntry>;
}
}
and the same for comments.
Hope this helps
Alex