Define association using database column and not entity type property - ef-code-first

public class Order {
public int OrderID {get; set;}
public DateTime DateOrdered { get; set; }
public ICollection<OrderLine> OrderLines { get; set; }
}
public class OrderLine{
public int OrderLineID { get; set; }
public int OrderID {get; set; } // I want to remove this
public string ItemName { get; set;}
public Int Qty { get; set; }
}
How would I map these using the Fluent API? I am using these in a repository pattern where Order will be the root of the aggregate. As such I do not want OrderLine to have a reference to Order or have an OrderID. Since the OrderLine only makes any sense because its a child of Order.
Currently I am using this:
HasMany<OrderLine>(x => x.OrderLines).WithRequired().HasForeignKey(x => x.OrderID);
I am using an existing database structure here and ideally I would map this using the database column name. So somehow tell it to use tblOrderLine.colOrderId rather then OrderLine.OrderID.

You can use the Map() method to map your FK
HasMany<OrderLine>(x => x.OrderLines)
.WithRequired()
.Map(m => m.MapKey("colOrderId"));

Related

.NET EF Inheritance without keys or constraints

It is possible to inherit from a type in dotnet EF without inherit the keys, indexes, etc?
I have these types:
public class Product : IEntity<long>
{
public long Id { get; set; }
public string Name { get; set; }
}
public class ProductVersion : Product
{
[Key]
public int ProductVersionId { get; set; }
public DateTime CreatedAt { get; set; }
}
I want ProductVersion to inherit all the properties from Product without creating any keys, constraints or navigation properties from the parent, just have the same properties and if are required or not, basically create a copy of the table columns.
The way you have it set up should remove the key constraint:
https://www.tektutorialshub.com/entity-framework-core/data-annotations-key-attribute-in-ef-core/
Adding [NotInherritedAttribute] should get rid of any of restraints you add:
https://learn.microsoft.com/en-us/dotnet/api/system.attributeusageattribute.inherited?view=net-6.0
[NotInheritedAttribute]
public class ProductVersion : Product{
[Key]
public int ProductVersionId { get; set; }
public DateTime CreatedAt { get; set; }
}

is there any way to pre-define a query in a model that runs whenever that model is called from context

i have model in my mvc 5 project named operations.
public class Operation
{
public int OperationID { get; set; }
public string Name { get; set; }
public decimal Commission { get; set; }
public int DepartmentID { get; set; }
public bool CommissionValidity { get; set; }
public bool IsHidden { get; set; }
public decimal Capacity { get; set; }
public virtual Department Department { get; set; }
}
requirement is whenever this model is called from context
like below
Var db = new ApplicationDbContext();
var Operations = db.Operations.tolist();
i want only the records to be loaded where IsHidden field is False without using where clause in query
is there any way like i make constructor or define getter Setter functions to acquire the goal.
If you're using Entity Framework Core, you can use a global query filter to achieve this.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Operation>().HasFilter(o => !o.IsHidden);
}
Entity Framework 6 doesn't have query filters. For that, you'd need to use a different property on your DbContext to return your visible entities:
public IQueryable<Operation> VisibleOperations
=> Set<Operation>().Where(o => !o.IsHidden);
However, you won't be able to use this filtered query to add or remove entities from the database, so you'll probably still need to expose the full IDbSet<Operation>, which won't have the filter applied.

Is ok to add [BsonAttribute] to POCOs?

I have an application, structured like this:
Application.Domain
Application.Web.Mvc
Application.MongoDb
In Application.Domain i keep all the POCOs of the application (the domain models).
public class Product
{
public string Id { get; set; }
public string ProductName { get; set; }
public DateTime CreatedDate { get; set; }
}
Now, because i am using MongoDb, i also need to use some of the [BsonAttribute], in order to customize the serialization process.
For example:
public class Product
{
[BsonId]
public string Id { get; set; }
public string ProductName { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local, DateOnly = true)]
public DateTime CreatedDate { get; set; }
}
If i add these attributes, i will need to also add a reference to MongoDB.Bson.Serialization.Attributes in the Application.Domain project, which i want to avoid.
I think the correct way to do this is to create mapping objects in the Application.MongoDb project, and always map them from POCO to MongoObjects and the other way around every time i work with MongoDb repos.
If this is the correct solution, isn't this a bit overkill?

Tree structure with reference to root in Entity Framework

I'm trying to model a tree structure for orders in Entity Framework. Right now I've go the following:
public class ProjectModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CustomerId { get; set; }
public virtual List<ProjectNode> Nodes { get; set; }
}
public class ProjectNode
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Path { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual List<ProjectNode> Children { get; set; }
}
What I need to be able to do is get a reference to the root ProjectModel at any level of ProjectNode in order to authorize a given user actually having permission to view and change the project which contains the ProjectNode.
public class ProjectNode {
public int ProjectId { get; set; } //<-- this
...
public class ProjectModel {
[Key]
public int Id { get; set; } //<-- containing the value of this
}
My question is whether its possible to have a theoretical ProjectId property populated at every level of the tree structure, or if I need to set it manually.
I had something working that at first blush appeared to allow this functionality, but upon further investigation only populated the ProjectId for ProjectNodes contained in the ProjectModel's Nodes property.
It seems to me like it would be super inefficient to recurse backwards through the structure to get to the root.
Credit due to #TestWell for this answer -
Apparently, all I needed to do for EF to automatically populate the ProjectId property on the ProjectNode was to change the name of the Id property in ProjectModel to ProjectId.
Unfortunately, this doesn't appear to work if I add a CustomerId property to the ProjectNode that I would like automatically populated from the property of the same name on the node's root ProjectModel, which I realized is the more efficient solution to what I'm trying to do.

Is it OK to declare a DBSet in the context for both a base table and a derived table?

I have a SalesOrder table which inherits from a SalesDocument table using Table Per Type Inheritance
The ( simplified) table classes are;
[Table("SalesDocumentHeaders")]
public abstract class SalesDocumentHeader
{
[ForeignKey("CreatedByUserId")]
public virtual User CreatedBy { get; set; }
[Required]
public int CreatedByUserId { get; set; }
[Required]
public virtual DateTime? DocumentDate { get; set; }
[Required]
public String ReferenceNumber { get; set; }
}
[Table("SalesOrders")]
public class SalesOrder : SalesDocumentHeader
{
[Required]
public String CustomerOrderNumber { get; set; }
public DateTime? DeliverBy { get; set; }
public virtual SortableBindingList<SalesOrderLine> Lines { get; set; }
}
The context contains
public DbSet<SalesOrder> SalesOrders { get; set; }
public DbSet<SalesDocumentHeader> SalesDocumentHeaders { get; set; }
It doesn't strictly need the SalesOrders DBSet, since SalesOrder inherits from SalesDocumentHeader however I find it convenient.
It seems to work OK, but I am worried that there are 2 ways of reaching the same record , am I doing something wrong?
Usually you only need to keep the DBSet for the base table. This helps when you have multiple derived tables (call them A and B) and you need to decide the actual type dynamically.
For example if you have another entity which references type A or B (like a user can have different types of contact information), you can reference the base table and EF will resolve the correct concrete type at runtime. Though of course this adds some extra casting code.

Resources