EF4 and UnitOfWork - How to make custom properties work - entity-framework

Say I have:
public class A
{
public virtual int Id { get; set; }
}
public class ARepository
{
private SomeContext _context;
public ARepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
}
public A GetAById(int aId)
{
return _context.A.Where(o => o.Id == aId).SingleOrDefault();
}
}
public class B
{
public virtual int Id { get; set; }
public virtual Category Category { get ; set; } //enum with NEW and OLD values
public virtual int Quantity { get; set; }
}
public class BRepository
{
private SomeContext _context;
public BRepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
}
public B GetBById(int bId)
{
return _context.B.Where(o => o.Id == bId).SingleOrDefault();
}
}
And I'm working with Entity Framework (4.1 code first).
How would I implement for example a custom property in A class like:
//returns the total of all B objects in the context where the category is NEW
public int NewBTotals
{
}
And not having to create a context?
Hopefully my question is clear enough, if not please let me know and I'll try to be more descriptive of what I want to achieve (ran out of time).

I found that even by B not having a foreign key to A, I can create a navigation property from A to B and vice versa which kind of solves the problem on its own.

Related

Dependency injection not working in web api call

Hi I am trying to build angular 2 web application using WebAPI, Entityframework that is loosely coupled using dependency injection. I am using unity for dependency injection. I have created multiple projects in one solution to address the separation concerns.
I have configured the dependency in unity.config however when i execute the webapi application and type the following url http://localhost:8702/api/allcustomers , I get message saying the customer controller doesn't have parameter-less constructor. I have set my break points in unity.config which never get hit
I would like to to understand if my implementation is correct as well
Below is the structure of my solution
CustomerOrder.Business.Objects
CustomerOrder.Data.Objects (references the business object)
CustomerOrder.Service.Api (references business object and service implementation)
CustomerOrder.Service.Implementation (references business objects and data objects)
CustomerOrder.Web (Yet to implement)
Below is the code
CustomerOrder.Business.Objects
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public int? Zip { get; set; }
}
CustomerOrder.Data.Objects
public class CustomerDao : ICustomerDao
{
IEnumerable<CustomerOrder.BusinessObjects.Customer> ICustomerDao.GetAllCustomers()
{
using (var customerOrderContext = new Entities())
{
return (from customer in customerOrderContext.Customers
select new CustomerOrder.BusinessObjects.Customer
{
Id = customer.Id,
FirstName = customer.FirstName,
LastName = customer.LastName,
Address = customer.Address,
City = customer.City,
Email = customer.Email,
Gender = customer.Gender,
State = customer.State,
Zip = customer.Zip
}).ToList();
}
}
}
public interface ICustomerDao
{
/// <summary>
/// Get All Customers
/// </summary>
/// <returns></returns>
IEnumerable<Customer> GetAllCustomers();
}
public interface IDaoFactory
{
ICustomerDao CustomerDao { get; }
}
}
public class DaoFactory : IDaoFactory
{
public DaoFactory(ICustomerDao CustomerDao, IProductDao ProductDao, IOrderDao OrderDao)
{
this.CustomerDao = CustomerDao;
}
public ICustomerDao CustomerDao { set; get; }
}
CustomerOrder.Service.Api
Unity.Config
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<ICustomerProvider, CustomerProvider>();
container.RegisterType<IOrderProvider, OrderProvider>();
container.RegisterType<IProductProvider, ProductProvider>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
CustomerController.cs
public class CustomerController : ApiController
{
private ICustomerProvider customerProvider;
public CustomerController(ICustomerProvider customerProvider)
{
this.customerProvider = customerProvider;
}
[Route("api/allcustomers")]
public IEnumerable<Customer> GetAllCustomers()
{
return customerProvider.GetAllCustomers();
}
CustomerOrder.Service.Implementation
public interface ICustomerProvider
{
IEnumerable<BusinessObjects.Customer> GetAllCustomers();
}
public class CustomerProvider : ICustomerProvider
{
private readonly IDaoFactory dataAccess;
public CustomerProvider(IDaoFactory dalFactory)
{
this.dataAccess = dalFactory;
}
public IEnumerable<BusinessObjects.Customer> GetAllCustomers()
{
IList<BusinessObjects.Customer> customerCollection = new List<BusinessObjects.Customer>();
dataAccess.CustomerDao.GetAllCustomers();
return customerCollection;
}
}
Context Class
namespace CustomerOrderData.EF
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class Entities : DbContext
{
public Entities()
: base("name=Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<OrderDetail> OrderDetails { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Product> Products { get; set; }
}
}
In CustomerProvider, the IDaoFactory is probably not getting resolved because it's not registered. Add this to the Unity.Config:
container.RegisterType<IDaoFactory , DaoFactory >();
Please try including a parameterless constructor into the customer controller.
public CustomerController() {}
You should register not only IDaoFactory and his constructor dependencies
container.RegisterType<IDaoFactory, DaoFactory>();
container.RegisterType<ICustomerDao, CustomerDao>();
container.RegisterType<IOrderDao, OrderDao>();
container.RegisterType<IProductDao, ProductDao>();

WCF + EF return object with FK

I am facing following issue: I have ProductOrder class which has ProductId as foreign key to Product class. When I invoke following method:
public IEnumerable<ProductOrder> GetOrders()
{
return OddzialDb.ProductOrders;
}
Orders are associated with Product so I can write something like this:
OddzialDb.ProductOrders.First().Product.Name;
but when it reaches Client it turns out that there is no association with Product which is null (only ProductId is included). In DbContext I have set
base.Configuration.ProxyCreationEnabled = false;
base.Configuration.LazyLoadingEnabled = false;
On the WCF Service side auto-generated by EF ProductOrder class looks as follows:
public partial class ProductOrder
{
public int Id { get; set; }
public Nullable<int> ProductId { get; set; }
public int Quantity { get; set; }
public virtual Product Product { get; set; }
}
What happens that it looses connections with tables associated by foreign keys?
Make your relationship virtual as in the example:
public class ProductOrder
{
public int Id { get; set; }
public virtual Product Product { get; set; }
public int ProductId { get; set; }
}
By turning your relationship virtual, the Entity Framework will generate a proxy of your ProductOrder class that will contain a reference of the Product.
To make sure it will work, Product also has to contain reference to ProductOrder:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ProductOrder> ProductOrders { get; set; }
}
Set these variables true on your DbContext:
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
On your WCF application, add the following class, which will allow for proxy serialization:
public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
{
public ApplyDataContractResolverAttribute()
{
}
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver =
new ProxyDataContractResolver();
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver =
new ProxyDataContractResolver();
}
public void Validate(OperationDescription description)
{
// Do validation.
}
}
Then on your ServiceContract interfaces you add the DataAnnotation [ApplyDataContractResolver] right among your other annotations such as [OperationContract], above any method signature that returns an entity:
[OperationContract]
[ApplyDataContractResolver]
[FaultContract(typeof(AtcWcfEntryNotFoundException))]
Case GetSingleByCaseNumber(int number);

Entity Framework Code First Map (Linked) Table?

I'm working with the EF code first approach and want to add a link (map) table. I am working off the below example and get the following error:
System.Data.Entity.Edm.EdmEntityType: : EntityType 'EmployeeDepartmentLink' has no key defined. Define the key for this EntityType.
Problem is I dont want a key on this table it just maps the two tables together:
public class Employee
{
[Key()]
public int EmployeeID;
public string Name;
}
public class Department
{
[Key()]
public int DepartmentID;
public string Name;
}
public class EmployeeDepartmentLink
{
public int EmployeeID;
public int DepartmentID;
}
I have tried a variety of things like adding the "[Key()]" attribute but it doesn't make sense for it to be used, and which field do I add it to? I am wondering if this sort of table model is even supported?
You are trying to make a "Many to Many" mapping.
To perform this, write this code:
public class Employee
{
[Key]
public int EmployeeId;
public string Name;
public List<Department> Departments { get; set; }
public Employee()
{
this.Departments = new List<Department>();
}
}
public class Department
{
[Key]
public int DepartmentId;
public string Name;
public List<Employee> Employees { get; set; }
public Department()
{
this.Employees = new List<Employee>();
}
}
then, in your DbContext:
public class YourContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public YourContext() : base("MyDb")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().
HasMany(c => c.Employees).
WithMany(p => p.Departments).
Map(
m =>
{
m.MapLeftKey("DepartmentId");
m.MapRightKey("EmployeeId");
m.ToTable("DepartmentEmployees");
});
}
}
For M:M relationship you have to create your join (link) class is as below.
public class EmployeeDepartmentLink
{
[Key, Column(Order = 0)]
public int EmployeeID;
[Key, Column(Order = 1)]
public int DepartmentID;
}
For more information check Create code first, many to many
I hope this will help to you.

EF 4.3 (Code First) - Custom ICollection Fails to catch new items

This is in reference to the question I asked regarding how to determine when items are added to the virtual ICollection property. As suggested, I have created a custom collection which inherits from Collection as shown below
public class EntityCollection<T> : Collection<T>
{
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
}
}
This is being used as
public class DbAppointment
{
public DbAppointment()
{
exceptionOcurrences = new EntityCollection<DbExceptionOcurrence>();
}
public virtual int AppointmentId { get; set; }
public virtual string Subject { get; set; }
public virtual string Body { get; set; }
public virtual DateTime Start { get; set; }
public virtual DateTime End { get; set; }
private ICollection<DbExceptionOcurrence> exceptionOcurrences;
public virtual ICollection<DbExceptionOcurrence> ExceptionOcurrences
{
get { return exceptionOcurrences; }
set { exceptionOcurrences = value; }
}
}
The problem is the only time the overridden InsertItem method seems to get called is if I initialise the database with a custom initialiser (example code below) and override the seed method!! What am I doing wrong?
Cheers
Abs
public class ContextInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
new List<DbAppointment>
{
new DbAppointment{ Subject = "hello", Body="world", Start=DateTime.Now, End=DateTime.Now.AddMinutes(30)},
}.ForEach(a => context.Appointments.Add(a));
new List<DbExceptionOcurrence>
{
new DbExceptionOcurrence{ExceptionDate=DateTime.Now}
}.ForEach(eo => context.ExceptionOcurrences.Add(eo));
base.Seed(context);
}
}

code first with abstract class, the fk couldn't generated

please look at the code below.
class Program
{
static void Main(string[] args)
{
using (myContext context = new myContext())
{
Team t = new Team();
t.id = 1;
t.Name = "asd";
context.teamSet.Add(t);
context.SaveChanges();
}
}
}
public abstract class Base
{
public virtual int id { get; set; }
}
public abstract class Player : Base
{
public virtual string Name { get; set; }
public virtual int Number { get; set; }
public virtual Team team { get; set; }
[ForeignKey("team")]
public int teamId { get; set; }
}
public class Team : Base
{
public ICollection<Player> Players { get; set; }
public string Name { get; set; }
}
public class FootballPlayer : Player
{
public double Speed { get; set; }
}
public class BasketballPlayer : Player
{
public double Height { get; set; }
public double Speed { get; set; }
}
public class myContext : DbContext
{
public DbSet<Player> playerSet { get; set; }
public DbSet<Team> teamSet { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new BaseConfiguration()).Add(new PlayerConfiguration()).Add(new TeamConfiguration()).Add(new FootballConfiguration()).Add(new BasketballConfiguration());
}
}
public class BaseConfiguration : EntityTypeConfiguration<Base>
{
public BaseConfiguration()
{
HasKey(k => k.id);
Property(p => p.id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
public class PlayerConfiguration : EntityTypeConfiguration<Player>
{
public PlayerConfiguration()
{
Map(p=>{
p.MapInheritedProperties();
p.ToTable("Player");
});
}
}
public class TeamConfiguration : EntityTypeConfiguration<Team>
{
public TeamConfiguration()
{
Map(p =>
{
p.MapInheritedProperties();
p.ToTable("Team");
});
}
}
public class FootballConfiguration : EntityTypeConfiguration<FootballPlayer>
{
public FootballConfiguration()
{
ToTable("FootballPlayer");
}
}
public class BasketballConfiguration : EntityTypeConfiguration<BasketballPlayer>
{
public BasketballConfiguration()
{
ToTable("BasketballPlayer");
}
}
My Player class and Team Class are derived from Based Class, and FootballPlayer and BasketballPlayer are derived from Player. But in the generated database, Player table doesn't contain a FK teamId, it is only a common property. Furthermore, the FootballPlayer and BasketballPlayer tables don't contains the properties which derived from Player class. Anyone can help?
What inheritance mapping are you trying to achieve? At the moment you have TPC between Base and Player and TPT between Player and its derived types. If you want to have inherited properties in those derived types you must use TPC as well but in such case there should be no Player table in your database. To use TPC for player you must use MapInheritedProperties in their mapping configurations.