I have a problem with devising a many to many relationship in code first. EF is creating the Junction table and associating the Fk's as I would expect, however when i try to access the User's MailingList collection, there are no entries.
I've implemented test data on Initialise via Seeding, the data is al present in the database.
I think the problem lies with the constructors for Users and MailingLists, but I'm uncertain. I want to be able to navigate the navigational property of User.MailingLists.
var user = db.Users.Find(1);
Console.WriteLine("{0}", user.EmailAddress); //This is Fine
Console.WriteLine("{0}", user.Address.PostCode); /This is Fine
foreach (MailingList ml in user.MailingLists) // this is 0
{
Console.WriteLine("{0}", ml.Name);
}
My model is below:-
public class User : IEntityBase
{
public User()
{
MailingLists = new List<MailingList>();
}
public int Id { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string EmailAddress { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public virtual Address Address { get; set; }
public ICollection<MailingList> MailingLists { get; set; }
}
public class MailingList : IEntityBase
{
public MailingList()
{
Users = new List<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public ICollection<User> Users { get; set; }
}
public class Address : IEntityBase
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string City { get; set; }
public string County { get; set; }
public string PostCode { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
}
Any suggestions welcome.
You are neither eager loading the MailingList entries with the query, nor fulfulling the requirements for a lazy loading proxy so there is no way EF can populate the collection.
To allow lazy loading, change the MailingList property to be virtual to allow the EF proxy to override it.
To use eager loading, use Include() (an extension method in System.Data.Entity) in the query to specify that the MailingList should be loaded.
Related
I have created an AutoQuery function in my API with the use of the following code.
[Route("/cars/search")]
public class SearchCars : QueryDb<Car, CarDto>, IJoin<Car, Equipment, Colour, FuelType, Manufacturer>
{
public List<int> EquipmentIds { get; set; }
public List<int> ManufacturerIds { get; set; }
public List<int> ColourIds { get; set; }
}
The CarDto looks like this
public class CarDto
{
public int Id { get; set; }
public List<Equipment> Equipment { get; set; }
public Manufacturer Manufacturer { get; set; }
public int ManufactorId { get; set; }
public FuelType FuelType { get; set; }
public int FuelTypeId { get; set; }
public byte[] ProfileImage { get; set; }
}
I was wondering if there are any specific values the IJoin looks for, because when I try to use this I get "Could not infer relationship between Car and Equipment"
Car looks like this.
[AutoIncrement]
public int Id { get; set; }
public int FuelTypeId { get; set; }
[Required]
public List<Equipment> Equipment { get; set; }
[Required]
public List<int> EquipmentIds { get; set; }
[Required]
public byte[] ProfileImage { get; set; }
Equipment looks like this.
[AutoIncrement]
public int Id { get; set; }
public EquipmentType EquipmentType { get; set; }
[Required]
public int EquipmentTypeId { get; set; }
[Required]
public string Name { get; set; }
I realise that there would require alot of magic knowing that EquipmentIds is a list of Ids that it should check for in the Equipment table, but since everything else with ServiceStack is magic, I am giving it a try.
NB I have shortened some of the models because they are long and contains lots of information which is not needed in this case.
Any joins in AutoQuery need to follow OrmLite's Reference Conventions.
I am building ParkingReservation in DDD, In short means that people can invite place and when the car get in the camera identify the model and update the status of the place.
I divided the model to three Bounded contexts:
The first is Reservation Context that include the following objects:
`public class Lot
{
public int ID { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Place> Places { get; set; }
}
public class Place
{
public int ID { get; set; }
public int FloorNumber { get; set; }
public int RowNumber { get; set; }
public int ParkingNumber { get; set; }
}
public class Car
{
public int ID { get; set; }
public string Model { get; set; }
}
public class Driver
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public int Age { get; set; }
public Gender Gender { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public bool AcceptAdsToMail { get; set; }
public byte[] PictureData { get; set; }
public DateTime RegistrationTime { get; set; }
public DriverStatuses DriverStatuses { get; set; }
}
public class Reservation
{
public int ID { get; set; }
public Driver Driver { get; set; }
public Car Car { get; set; }
public Place Place { get; set; }
public DateTime OrderTime { get; set; }
public DateTime ParkingStartTime { get; set; }
public DateTime ParkingEndTime { get; set; }
public ParkingStatuses ParkingStatus { get; set; }
}
public class ParkingHistory
{
public int ID { get; set; }
public Place Place { get; set; }
public Driver Driver { get; set; }
public Car Car { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}`
The Parking Lot has list of places
the Driver reserve place through the application
the saved place saved in the Reservation object and when the parking time
elapsed, new parkinghistory added to parkinghistories list that belong to driver and car so you can watch history per car or driver.
for this context of Reservation:
(1) Is it correct to put Driver and Reservation for the Aggregate Roots? or maybe Lot too?
(2) Place is entity or value object?
Thank you
The main goal of your use case is scheduling. You need to think about a consistency boundary around that idea. To avoid time slots overlapping for a place in a lot you will need to create a new abstraction for the purpose.
"PlaceInLotReservations" sounds as a good option as an value object to serve as a factory for a Reservation aggregate. In order to represent reality of how scheduling works you should feed that aggregate in the context of a day, so "PlaceInLotReservationsRepository" should has a "findByDate" method that collects all Reservations for a place in a given datetime.
So the semantics would be something like:
val placeInLotReservations = PlaceInLotReservationsRepository.findBy(datetime)
val reservation = placeInLotReservations.reserveFor(car, driver, startingTime, endingTime)
ReservationsRepository.save(reservation)
If there are lot of reservations in a place and so race conditions you can even make the VO smaller by passing in day quarters instead of a day for the initial look up.
BTW, can and driver are VOs in the context of the Reservation aggregate (they are not aggregates).
You can also have the history by querying the Reservation repository, you donĀ“t need ParkingHistory.
Hope it helps.
i want use multiple model in one view and add records in multiple table from view
my db like below image:
(i work with vs2012 mvc4 and EF)
i create four model for each table and class "PreOrder" for repository of all
public class Orders
{
public long OrdersId { get; set; }
public string CustomerId { get; set; }
public long OrderListId { get; set; }
public int? CountProduct { get; set; }
public string CountPrice { get; set; }
public string VisitorsName { get; set; }
public DateTime? OrderDate { get; set; }
}
public class Product
{
public string ProductID { get; set; }
public string NameProduct { get; set; }
public string Price { get; set; }
}
public class Customers
{
public string CustomerID { get; set; }
[DisplayFormat(NullDisplayText = "-")]
public string Name { get; set; }
[DisplayFormat(NullDisplayText = "-")]
...
}
public class OrderList
{
public long OrderListID { get; set; }
public Nullable<long> OrdersId { get; set; }
public string ProductId { get; set; }
public Nullable<int> Count { get; set; }
public Nullable<decimal> DisCount { get; set; }
}
public class PreOrder
{
public Customers _Customer { set; get; }
public Product _Product { set; get; }
public Orders _Order { set; get; }
public OrderList _OrderList { set; get; }
}
i want use name,family,customerid from tblcustomers
and productId,NameProduct,Price from tblProducts
and all fields of tblOrders and tblOrderList
how can i create one view to fill tables Orders and OrderList??
i solved problem like below article:
How to Use ViewModel with ASP.NET MVC ?
How to Use ValueInjecter with Asp.net MVC ViewModel ?
I have a database table called TBLFIRM. I am using acc database-first model. EF prepares the sql wrong. What can be wrong on this object?
Thank you
My Syntax, a very simple call:
TBLFIRM d = VT.TBLFIRMs.FirstOrDefault(p => p.ID > 0);
The SQL syntax that EF 5 prepares
SELECT TOP (1)
[Extent1].[ID] AS [ID],
[Extent1].[DISTID] AS [DISTID],
[Extent1].[SESSIONKEY] AS [SESSIONKEY],
[Extent1].[NAME] AS [NAME],
[Extent1].[PHONE] AS [PHONE],
[Extent1].[EMAIL] AS [EMAIL],
[Extent1].[CREATEUSER] AS [CREATEUSER],
[Extent1].[CREATEDATE] AS [CREATEDATE],
[Extent1].[UPDATEUSER] AS [UPDATEUSER],
[Extent1].[UPDATEDATE] AS [UPDATEDATE],
[Extent1].[AUTHORIZEDUSERNAME] AS [AUTHORIZEDUSERNAME],
[Extent1].[AUTHORIZEDUSEREMAIL] AS [AUTHORIZEDUSEREMAIL],
[Extent1].[AUTHORIZEDUSERPHONE] AS [AUTHORIZEDUSERPHONE],
[Extent1].[SENDEMAIL] AS [SENDEMAIL],
[Extent1].[REPLYEMAIL] AS [REPLYEMAIL],
[Extent1].[ACTIVE] AS [ACTIVE],
[Extent1].[CANLOGIN] AS [CANLOGIN],
[Extent1].[INTERNALNAME] AS [INTERNALNAME],
[Extent1].[TBLDISTRIBUTOR_ID] AS [TBLDISTRIBUTOR_ID]
FROM [dbo].[TBLFIRMs] AS [Extent1]
WHERE [Extent1].[ID] > 0
Context Class
public DbSet<TBLFIRM> TBLFIRMs { get; set; }
TBLFirm Class
public partial class TBLFIRM
{
public TBLFIRM()
{
this.TBLFIRMSETTINGS = new HashSet<TBLFIRMSETTING>();
this.TBLFIRMSMTPs = new HashSet<TBLFIRMSMTP>();
this.TBLMAILFIRMMATCHes = new HashSet<TBLMAILFIRMMATCH>();
this.TBLMAILGROUPs = new HashSet<TBLMAILGROUP>();
this.TBLMAILTEMPLATEs = new HashSet<TBLMAILTEMPLATE>();
this.TBLSCHEDULEs = new HashSet<TBLSCHEDULE>();
this.TBLUSERGROUPs = new HashSet<TBLUSERGROUP>();
this.TBLUSERS = new HashSet<TBLUSER>();
}
public int ID { get; set; }
public int DISTID { get; set; }
public string SESSIONKEY { get; set; }
public string NAME { get; set; }
public string PHONE { get; set; }
public string EMAIL { get; set; }
public string CREATEUSER { get; set; }
public Nullable<System.DateTime> CREATEDATE { get; set; }
public string UPDATEUSER { get; set; }
public Nullable<System.DateTime> UPDATEDATE { get; set; }
public string AUTHORIZEDUSERNAME { get; set; }
public string AUTHORIZEDUSEREMAIL { get; set; }
public string AUTHORIZEDUSERPHONE { get; set; }
public string SENDEMAIL { get; set; }
public string REPLYEMAIL { get; set; }
public Nullable<bool> ACTIVE { get; set; }
public Nullable<bool> CANLOGIN { get; set; }
public string INTERNALNAME { get; set; }
public virtual TBLDISTRIBUTOR TBLDISTRIBUTOR { get; set; }
public virtual ICollection<TBLFIRMSETTING> TBLFIRMSETTINGS { get; set; }
public virtual ICollection<TBLFIRMSMTP> TBLFIRMSMTPs { get; set; }
public virtual ICollection<TBLMAILFIRMMATCH> TBLMAILFIRMMATCHes { get; set; }
public virtual ICollection<TBLMAILGROUP> TBLMAILGROUPs { get; set; }
public virtual ICollection<TBLMAILTEMPLATE> TBLMAILTEMPLATEs { get; set; }
public virtual ICollection<TBLSCHEDULE> TBLSCHEDULEs { get; set; }
public virtual ICollection<TBLUSERGROUP> TBLUSERGROUPs { get; set; }
public virtual ICollection<TBLUSER> TBLUSERS { get; set; }
}
After a deeper research I was able to find and fix the problem thanks to a reply by BRian Rogers # Code First vs. Database First.
If you are approaching Database or Model First the the connection string must have a metadata, otherwise EF interprets this as Code First approach.
As I was calling the library holding EF objects from a web site, the web.config's connectionstring was a plaing database connection.
<add name="EmmContext" connectionString="Data Source=.;Initial Catalog=GPMM;Persist Security Info=True;User ID=********;Pwd=******" providerName="System.Data.SqlClient"/>
After changing it to
<add name="EmmContext" connectionString="metadata=res://*/DAL.DBModel.csdl|res://*/DAL.DBModel.ssdl|res://*/DAL.DBModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=GPMM;persist security info=True;user id=*******;password=********;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient"/>
it worked like a charm.
Just wanted to share this particular experience. Thank you Brian Rogers! :-)
I'm new with AutoMapper and have a problem I'm trying to solve.
If I have a source class like this:
public class Membership
{
public int MembershipId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string OrganizationName { get; set; }
public List<Address> Addresses { get; set; }
}
And the Address class looks like this:
public class Address
{
public int AddressId{ get; set; }
public int RefAddressTypeId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public bool IsPreferredAddress { get; set; }
}
My destination class is:
public class UserInformationModel
{
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Organization { get; set; }
public string EmailAddress { get; set; }
public PhysicalAddress BillingAddress { get; set; }
public PhysicalAddress ShippingAddress { get; set; }
}
And the destination address class is:
public class PhysicalAddress
{
public AddressType AddressType{get; set;}
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
I have set up a mapping like this:
Mapper.CreateMap<MinistryMattersIntegration.BusinessObjects.Entities.Cokesbury.Membership, UserInformationModel>()
.ForMember(dest => dest.Organization, opt => opt.MapFrom(src=>src.OrganizationName));
This is working for Membership to UserInformationModel, but now I need to get addresses working. One important thing to note, though, is that the destination is a single billing address and a single shipping address while in the original model, all the address are stored as a list. The way you find the shipping and billing addresses out of the list is by looking at the RefAddressTypdId and the IsPreferredAddress. Only one preferred address may exist with a particular RefAddressTypeId.
So, my question is, how do you get AutoMapper to do this kind of mapping? Is it possible, or am I better off just going with regular mapping code?
You'll want to use the Custom Value Resolvers feature of AutoMapper. So you'd setup a Custom Resolver to map from your list to your single entity using the IsPreferredAddress flag to find it.
The documentation is pretty good for the Custom Resolvers so you should be fine figuring it out from there.