Why do I need HashSet in many-to-many relation? - asp.net

I have found many tutorials that use HashSet ex
this.Supplier = new HashSet<supplier>();
In many-to-many relation. But som tutorials use the code below without HashSet (no more or less)
public partial class Product
{
public Product()
{
this.Supplier = new HashSet<supplier>();
}
public long ProductID { get; set; }
public string ProductName { get; set; }
//navigation property to Supplier
public virtual ICollection<supplier> Supplier { get; set; }
}
public partial class Supplier
{
public Supplier()
{
this.Product = new HashSet<product>();
}
public long SupplierID { get; set; }
public string SupplierName { get; set; }
// navigation property to Product
public virtual ICollection<product> Product { get; set; }
}
When I tested the code above and deleted
public xxxx()
{
this.xxxx = new HashSet<xxxx>();
}
I still got an association table and a many-to-many relation.
Why do I need HashSet?

Usually many-to-many relationship defined with ICollection in both table models:
public virtual ICollection<supplier> Supplier { get; set; }
public virtual ICollection<product> Product { get; set; }
The presence of ICollection on models means that lazy loading is enabled, allowing EF to create derived classes for them.
About the use of HashSet inside model generations, ChrisV said in HashSet in EF many to many:
HashSet implements a hash table that is very efficient for a lot of
operations, for instance searching a large set for a single item.
The usage of HashSet by default primarily based on efficiency reasons besides of non-null value, such like Yuval Itzchakov said in Entity Framework:Why the collection type of entity class need to be instanced in the default constructor?:
A HashSet is used because it guarantees that two values which are
equal to each other (which are equality checked by looking at their
GetHashCode and Equals methods) only appear once in the collection.
And yes, you can change the concrete type to any type which implements
ICollection<T>.
The explanations above can be summarized as "HashSet is initialization step of ICollection interface inside model's constructor which guarantees equality between each related model members". EF itself doesn't care what implementations should be apply on ICollection for table models, you can use List<T> in constructor replacing HashSet<T> and many-to-many relationship still doesn't affected.
Inside your template model (.tt file), you may see these lines to generate HashSet<T> by default as it implements ICollection:
foreach (var navigationProperty in collectionNavigationProperties)
{
#>
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
}
You may doing experiments by removing or changing HashSet<T> initialization when the model is re-generated, however I considered not a good practice to remove it for large amount of data operations.

Related

SQLite-Net Extensions | Foreign Key Reference to same entity

I am facing an issue in using SQLite-Net Extensions to save data in local DB in scenario where the foreign key is referencing the same entity (self-join).
Example – Employee and Manager. Every employee has a manager and a manager is also an employee. I am facing issues in saving data in such cases. It will be really helpful if you can provide some insights. Does this extension support this kind of relationship?
Yes, relationships between objects of the same class are supported, but the foreign keys and inverse properties must be explicitly specified in the relationship property attribute because the discovery system will get it wrong as there are be two relationships with the same type.
This example is extracted from the project readme:
public class TwitterUser {
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[ManyToMany(typeof(FollowerLeaderRelationshipTable), "LeaderId", "Followers",
CascadeOperations = CascadeOperation.CascadeRead)]
public List<TwitterUser> FollowingUsers { get; set; }
// ReadOnly is required because we're not specifying the followers manually, but want to obtain them from database
[ManyToMany(typeof(FollowerLeaderRelationshipTable), "FollowerId", "FollowingUsers",
CascadeOperations = CascadeOperation.CascadeRead, ReadOnly = true)]
public List<TwitterUser> Followers { get; set; }
}
// Intermediate class, not used directly anywhere in the code, only in ManyToMany attributes and table creation
public class FollowerLeaderRelationshipTable {
public int LeaderId { get; set; }
public int FollowerId { get; set; }
}
As you can see here we have a many-to-many between Twitter users. In your case it will be a one-to-many, so you won't need the intermediate table and you'll need the foreign key (ManagerId for example) in your Person class.

EF Code First: One-to-One One-way Relationship

I regularly have the following structure:
MyClass
public virtual ICollection<Version> Versions { get; set; }
public virtual Version CurrentVersion { get; set; }
That is, there is a list of stuff, and some class both points to that list, and one specific item in that list - either the current version of many versions, the next upcoming event in a list of events, etc.
In my schema what I'd like to end up with is a Foreign Key pointing from Version to MyClass - that much works out properly. But then I'd like a Foreign Key pointing from MyClass to Version representing the CurrentVersion property, with no Foreign Key pointing back - I don't want the extra storage or bother of telling a Version what MyClass it's the CurrentVersion for, if any. Put another way, I'd like this second relationship to be one-way from MyClass to Version, even though it's one-to-one.
What EF Code First gives me instead is the normal one-to-many on the first property, with the FK from Version to MyClass, but then a full one-to-one relationship on the second property with an FK pointing in both directions - so the underlying schema for Version ends up with MyClass_Id and MyClass_Id1.
So, is there a way to get a one-way relationship in EF Code First without resorting to the Fluent API? It looked like maybe System.ComponentModel.DataAnnotations.Schema.InverseProperty had a shot at it, but it didn't seem to offer a way to say "Don't generate one."
The key is to specify the InverseProperty on the property that points back, so that EF realizes it's to the Many-to-Many, not to the One-to-One.
public class MyClass
{
public int Id { get; set; }
public Version CurrentVersion { get; set; }
public ICollection<Version> Versions { get; set; }
}
public class Version
{
public int Id { get; set; }
[InverseProperty("Versions")]
public Versioned Versioned { get; set; }
}

Code First Generic Repository with existing Database tables

I have a Generic Repository class using code first to perform data operations.
public class GenericRepository<T> where T : class
{
public DbContext _context = new DbContext("name=con");
private DbSet<T> _dbset;
public DbSet<T> Dbset
{
set { _dbset = value; }
get
{
_dbset = _context.Set<T>();
return _dbset;
}
}
public IQueryable<T> GetAll()
{
return Dbset;
}
}
I have an entity class Teacher, which maps to an existing table "Teacher" in my database, with exactly the same fields.
public class Teacher
{
public Teacher()
{
//
// TODO: Add constructor logic here
//
}
public int TeacherID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
I have the following code below which binds data from Teacher to a repeater control.
GenericRepository<Teacher> studentrepository = new GenericRepository<Teacher>();
rptSchoolData.DataSource = studentrepository.GetAll().ToList();
rptSchoolData.DataBind();
But I get an exception exception "The entity type Teacher is not part of the model in the current context". Do I have to do any additional work when using an existing database for code first?
You must create a context class that derives from DbContext. The class should have properties of type DbSet<T> which will give EF enough information to create and communicate with a database with default naming and association conventions. It will use properties like Student.Teacher (if any) to infer foreign key associations:
public class MyContext: DbContext
{
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Student> Students { get; set; }
...
}
If the defaults are not what you want, or when you've got an existing database that you want to match with the names and associations in your model you can do two (or three) things:
Override OnModelCreating to configure the mappings manually. Like when the tables in the database have those ugly prefixes (to remind people that they see a table when they see a table):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Teacher>()
.Map(e => e.ToTable("tblTeacher"));
...
}
(Less favorable) Use data annotations to do the same.
Turn it around and use Entity Framework Powertools to reverse-engineer a database into a class model including fluent mappings and a DbContext-derived context. Maybe easier to modify an existing model than to start from scratch.

What's Automapper for?

What’s Automapper for?
How will it help me with my domain and controller layers (asp.net mvc)?
Maybe an example will help here...
Let's say you have a nicely-normalized database schema like this:
Orders (OrderID, CustomerID, OrderDate)
Customers (CustomerID, Name)
OrderDetails (OrderDetID, OrderID, ProductID, Qty)
Products (ProductID, ProductName, UnitPrice)
And let's say you're using a nice O/R mapper that hands you back a well-organized domain model:
OrderDetail
+--ID
+--Order
|--+--Date
|--+--Customer
|-----+--ID
|-----+--Name
+--Product
|--+--ID
|--+--Name
|--+--UnitPrice
+--Qty
Now you're given a requirement to display everything that's been ordered in the last month. You want to bind this to a flat grid, so you dutifully write a flat class to bind:
public class OrderDetailDto
{
public int ID { get; set; }
public DateTime OrderDate { get; set; }
public int OrderCustomerID { get; set; }
public string OrderCustomerName { get; set; }
public int ProductID { get; set; }
public string ProductName { get; set; }
public Decimal ProductUnitPrice { get; set; }
public int Qty { get; set; }
public Decimal TotalPrice
{
get { return ProductUnitPrice * Qty; }
}
}
That was pretty painless so far, but what now? How do we turn a bunch of OrderDetails into a bunch of OrderDetailDtos for data binding?
You might put a constructor on OrderDto that takes an OrderDetail, and write a big mess of mapping code. Or you might have a static conversion class somewhere. Or, you could use AutoMapper, and write this instead:
Mapper.CreateMap<OrderDetail, OrderDetailDto>();
OrderDetailDto[] items =
Mapper.Map<OrderDetail[], OrderDetailDto[]>(orderDetails);
GridView1.DataSource = items;
There. We've just taken what would otherwise have been a disgusting mess of pointless mapping code and reduced it into three lines (really just two for the actual mapping).
Does that help explain the purpose?
If you have an object of one type and you want to populate the properties of an object of another type using properties from the first type, you have two choices:
Manually write code to do such a mapping.
Use a tool that will automatically handle this for you.
AutoMapper is an example of 2.
The most common use is to flatten models into a data transfer objects (or, in general, mapping across layer boundaries). What's very nice about AutoMapper is that for common scenarios you don't have to do any configuring (convention over configuration).
Map objects between layers. Good example: Here

Slim version of Large Object/Class

I have a product class which contains 11 public fields.
ProductId
ShortTitle
LongTitle
Description
Price
Length
Width
Depth
Material
Img
Colors
Pattern
The number of fields may grow with attributes for more specific product tyes. The description may contain a large amount of data.
I want to create a slim version of this product class that only contains the data needed. I'm only displaying 4 of the 12 fields when listing products on a category page. It seems like a waste to retrieve all of the data when most of it isn't being used.
I created a parent class of ProductListing that contains the 4 fields I need for the category page
ProductId
ShortTitle
Price
Img
Then created a class of Product that inherits from ProductListing containing all product data. It seems backwards as "ProductListing" is not a kind of "Product" but I just started reading about inheritance a few months ago so it's stil a little new to me.
Is there a better way to get a slim object so I'm not pulling data I don't need?
Is the solution I have in place fine how it is?
I personally do not favor inheritance for these kinds of problems because it can become confusing over time. Specifically, I try to avoid having two concrete classes in my inheritance hierarchy where one inherits from the other and both can be instantiated and used.
How about creating a ProductCoreDetail class that has the essential fields you need and aggregating it inside of the Product class. You can still expose the public fields by declaring them as public fields and proxying them to the nested ProductCoreDetail instance.
The benefit of this model is that any shared implementation code can be placed in ProductCoreDetail. Also, you can choose to define an additional interface IProductCoreDetail that both Product and ProductCoreDetail implement so that you can pass either instance to methods that just care about code information. I would also never exposed the aggregate instance publicly to consumer of Product.
Here's a code example:
// interface that allows functional polymorphism
public interface IProductCoreDetail
{
public int ProductId { get; set; }
public string ShortTitle { get; set; }
public decimal Price { get; set; }
public string Img { get; set; }
}
// class used for lightweight operations
public class ProductCoreDetail : IProductCoreDetail
{
// these would be implemented here..
public int ProductId { get; set; }
public string ShortTitle { get; set; }
public decimal Price { get; set; }
public string Img { get; set; }
// any additional methods needed...
}
public class Product : IProductCoreDetail
{
private readonly ProductCoreDetail m_CoreDetail;
public int ProductId { get { return m_CoreDetail.ProductId; } }
public string ShortTitle { get { return m_CoreDetail.ShortTitle; } }
public decimal Price { get { return m_CoreDetail.Price; } }
public string Img { get { return m_CoreDetail.Img; } }
// other fields...
public string LongTitle
public string Description
public int Length
public int Width
public int Depth
public int Material
public int Colors
public int Pattern
}
I agree with LBushkin that inheritence is the wrong approach here. Inheritence suggests that TypeB is a TypeA. In your case, the relationship is not quite the same. I used to create classes that were subsets of a large entity for things like search results, list box items, etc. But now with C# 3.5's anonymous type support and LINQ projections, I rarely need to do that anymore.
// C#
var results = from p in products
select new {
p.ProductId,
p.ShortTitle,
p.Price,
p.Img };
// VB.NET
Dim results = From p in products _
Select p.ProductId, p.ShortTitle, p.Price, p.Img
This creates an unnamed type "on-the-fly" that contains only the fields you specified. It is immutable so the fields cannot be changed via this "mini" class but it supports equality and comparison.
But when I do need to create a named type, I typically just create a separate class that has no relationship to the main class other than a lazy-loaded reference to the "full" version of the object.
I wouldn't use a separate class or inheritance.
For your slim version, why not just retrieve only the data you need, and leave the other fields empty? You might have two queries: one that fills all the fields, and another that only fills the slim fields. If you need to differentiate between the two, that's easy if one of the non-slim fields is NOT NULL in your DB; just check for null in the object.

Resources