I am trying to use code first to generate a database for an asp.net mvc application. the OrderItem class does get generated as OrderItems table in the database but I end up without having any access to it. what can I do to allow the following for example: db.OrderItems.Find(id);
the model is as follows:
namespace CustomerOrders.Models{
public class Customer
{
public virtual int CustomerID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Company { get; set; }
public virtual string Email { get; set; }
public virtual string EmailCheck { get; set; }
}
public class Order
{
public virtual int OrderID { get; set; }
public virtual int CustomerID { get; set; }
public virtual DateTime OrderDate { get; set; }
public virtual double OrderTotal { get; set; }
public virtual double Tax { get; set; }
public virtual Customer Customer { get; set; }
public virtual List<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public virtual int OrderItemID { get; set; }
public virtual int OrderID { get; set; }
public virtual int ProductID { get; set; }
public virtual double PricePerItem { get; set; }
public virtual double Quantity { get; set; }
public virtual Product Product { get; set; }
public Order Order { get; set; }
}
public class Product
{
public virtual int ProductID { get; set; }
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual double Price { get; set; }
}
}
You probably haven't got the declaration in your dbContext so Open up the dbContext and add this:
public DbSet<OrderItem> OrderItems { get; set; }
you should end up with this:
public class CustomerOrdersDB : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
}
Related
I want to configure a one-to-many relationship in Ef core. As you see I have a class for order and the other one for OrderItems.
I do it when I use NHibernate.of course, I consider orderItem class as ValueObject.But I want to do it using EF Core.
public class Order
{
public long Id { get; set; }
public long CustomerId { get; set; }
public DateTime OrderDateTime { get; set; }
public ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public string BookId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal? Discount { get; set; }
public decimal Total { get; set; }
public Order Order { get; set; }
}
you should define meta data [ForeignKey] with type of primary key in order entity. after that ef core automatically set in db by your chosen name
public class Order
{
public long Id { get; set; }
public long CustomerId { get; set; }
public DateTime OrderDateTime { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public long Id { get; set; }
[ForeignKey(nameof(OrderId)]
public virtual Order Order { get; set; }
public long OrderId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal? Discount { get; set; }
public decimal Total { get; set; }
}
Here is a simple demo like below:
1.Model:
public class Order
{
public long Id { get; set; }
public long CustomerId { get; set; }
public DateTime OrderDateTime { get; set; }
public ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public int OrderItemId { get; set; }//you need to define a primary key for OrderItem model
public string BookId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal? Discount { get; set; }
public decimal Total { get; set; }
public Order Order { get; set; }
}
2.DbContext:
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.HasMany(c => c.OrderItems)
.WithOne(e => e.Order);
}
}
3.Startup.cs:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyDbContext")));
4.appsettings.json:
"ConnectionStrings": {
"MyDbContext": "Server=(localdb)\\mssqllocaldb;Database=DatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true"
}
5.Run command line on Package Nuget Manager:
PM>add-migration init
PM>update-database
Model
public class Order {
public long Id { get; set; }
public long CustomerId { get; set; }
public DateTime OrderDateTime { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
[Key]
public int OrderItemId { get; set; }
public string BookId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal? Discount { get; set; }
public decimal Total { get; set; }
public long OrderId{get;set;} // ForeignKey OrderId
[ForeignKey("OrderId")]
public virtual Order Order { get; set; }
}
// open PackageManager console
PM>add-migration "orderItem changed"
PM>update-database
A very beginner question:
I have two classes, Review and ReviewSentences:
public class Review
{
public virtual int recordId { get; set; }
public virtual string reviewerId { get; set; }
public virtual string reviewerName { get; set; }
public virtual string country { get; set; }
public virtual string zipCode { get; set; }
public virtual string reviewProduct { get; set; }
public virtual string reviewText { get; set; }
public virtual string reviewTextLanguage { get; set; }
public virtual double sentimentScore { get; set; }
public virtual bool isScoreRefined { get; set; }
}
pulic class ReviewSentences
{
public virtual int recordId { get; set; }
public virtual int reviewId { get; set; }
public virtual int sentenceId { get; set; }
public virtual string sentence { get; set; }
public virtual double sentimentScore { get; set; }
}
The property ReviewSentences.reviewId is a foreign key referring to Review.recordId. One review can have many sentences (Review:ReviewSentences is 1:Many)
I have been trying for a long time now but unable to replicate the following query in terms of NHibernate with session.CreateCriteria:
select * from Reviews r
left join
ReviewSentences rs
on
r.RecordId = rs.ReviewId
where rs.ReviewId is null
The query gives me all reviews from the Review table that do not have any records in the ReviewSentences table.
It is a matter of mapping you should include an array of ReviewSentences in your Review class and map it correctly.
public class Review
{
public virtual int recordId { get; set; }
public virtual string reviewerId { get; set; }
public virtual string reviewerName { get; set; }
public virtual string country { get; set; }
public virtual string zipCode { get; set; }
public virtual string reviewProduct { get; set; }
public virtual string reviewText { get; set; }
public virtual string reviewTextLanguage { get; set; }
public virtual double sentimentScore { get; set; }
public virtual bool isScoreRefined { get; set; }
public virtual IList<ReviewSentences> sentences { get; set; }
}
pulic class ReviewSentences
{
public virtual int recordId { get; set; }
public virtual int reviewId { get; set; }
public virtual int sentenceId { get; set; }
public virtual string sentence { get; set; }
public virtual double sentimentScore { get; set; }
}
then in the mapping you should refer sentences as a reference.
but you did not said which kind of mapping your using (Fluent, conformist, etc.)
Fixed the mapping in hbm.xml files and got the required results using:
var reviews= session.CreateCriteria<Review>("r")
.CreateCriteria("r.sentences", JoinType.LeftOuterJoin)
.Add(Restrictions.IsNull("recordId"))
.List<Review>();
I have the following models in my solution:
internal class Customer
{
[Key]
public int CustomerId { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[MaxLength(12)]
public string PhoneNumber { get; set; }
}
internal class Product
{
[Key]
public int ProductId { get; set; }
[MaxLength(100)]
public string ProductName { get; set; }
public decimal Price { get; set; }
public double ProductWeight { get; set; }
public bool InStock { get; set; }
}
internal class Order
{
[Key]
public int OrderId { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public DateTime OrderDate { get; set; }
[MaxLength(30)]
public string PoNumber { get; set; }
}
class Cart
{
public virtual ICollection<Order> Orders { get; set; }
public virtual ICollection<Product> Products { get; set; }
public uint Quantity { get; set; }
}
...and DB context
class Store : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Cart> Carts { get; set; }
}
When I debug, an exception is thrown saying "'Carts' is based on type 'Cart' that has no keys defined".
I've removed the Cart class from the DB context and the solution runs fine.
I've tried several different ways to declare the keys in the Cart class including:
[ForeignKey("Order")]
[Column(Order = 1)]
public int OrderId { get; set; }
public Order Order { get; set; }
[ForeignKey("Product")]
[Column(Order = 2)]
public int ProductId { get; set; }
public Product Product { get; set; }
or
[Key]
public int OrderId { get; set; }
[Key]
public int ProductId { get; set; }
Any ideas where I might be going wrong? (Please keep in mind this is an educational project so feedback on the DB design is unnecessary)
I'm using entity framework and have some classes
public class Lot
{
public int LotId { get; set; }
public string Description { get; set; }
public virtual Product Product { get; set; }
public virtual ApplicationUser Owner { get; set; }
public virtual ApplicationUser CurrentCustomer { get; set; }
public virtual ICollection<ApplicationUser> AllCustomers { get; set; }
public virtual AuctionDates AuctionDates { get; set; }
public virtual AuctionPrices AuctionPrices { get; set; }
public virtual State State { get; set; }
public virtual ProductImages Images { get; set; }
}
and
public class ApplicationUser : IdentityUser
{
[Required]
public virtual UserInfo UserInfo { get; set; }
public virtual ICollection<Lot> SelledLots { get; set; }
public virtual ICollection<Lot> BuyedLots { get; set; }
public virtual ICollection<Lot> ParticipatedLots { get; set; }
}
And the question is how can I set configuration for mapped user who Sell Lot(ApplicationUser) in Owner(Lot), who buy lot(ApplicationUser) in current customer(Lot) and so on. Thanks a lot.
I've finally found the answer. In this situation data annotation InverseProperty should be used. https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449317867/ch04s03.html
public class Lot
{
public int LotId { get; set; }
public string Description { get; set; }
public virtual Product Product { get; set; }
[InverseProperty("SelledLots")]
public virtual ApplicationUser Owner { get; set; }
[InverseProperty("BuyedLots")]
public virtual ApplicationUser CurrentCustomer { get; set; }
[InverseProperty("ParticipatedLots")]
public virtual ICollection<ApplicationUser> AllCustomers { get; set; }
public virtual AuctionDates AuctionDates { get; set; }
public virtual AuctionPrices AuctionPrices { get; set; }
public virtual State State { get; set; }
public virtual ProductImages Images { get; set; }
}
These are my entities:
public class Subscription : BaseItem
{
public virtual DateTime DateStart { get; set; }
public virtual DateTime? DateEnd { get; set; }
public virtual int Status { get; set; }
public virtual Account Account { get; set; }
public virtual Theater Theater { get; set; }
public virtual Agent Agent { get; set; }
}
public class Account : BaseItem
{
public virtual string LegalName { get; set; }
public virtual string FirstName { get; set; }
public virtual string UrlName { get; set; }
public virtual string Address1 { get; set; }
public virtual string Address2 { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string ZipCode { get; set; }
public virtual string Country { get; set; }
public virtual string Tel { get; set; }
public virtual string Tel2 { get; set; }
public virtual string Fax { get; set; }
public virtual string Mobile { get; set; }
public virtual string Email { get; set; }
public virtual string Website { get; set; }
public virtual int DefaultVatRate { get; set; }
public virtual bool Bankrupt { get; set; }
public virtual string ExternalId { get; set; }
public virtual bool DoNotContact { get; set; }
public virtual bool NotInterested { get; set; }
public virtual Group Group { get; set; }
public virtual IList<Header> Headers { get; set; }
public virtual IList<Note> Notes { get; set; }
public virtual IList<Order> Orders { get; set; }
public virtual IList<Subscription> Subscriptions { get; set; }
}
public class Order : BaseItem
{
public virtual int Number { get; set; }
public virtual DateTime Date { get; set; }
public virtual string Description { get; set; }
public virtual double Amount { get; set; }
public virtual string Attachment { get; set; }
public virtual string AttachmentFilename { get; set; }
public virtual string AttachmentMimetype { get; set; }
public virtual bool? PaidToTheater { get; set; }
public virtual DateTime? DatePaidToTheater { get; set; }
public virtual bool? CashinByTheater { get; set; }
public virtual Account Account { get; set; }
public virtual Theater Theater { get; set; }
public virtual Agent Agent { get; set; }
public virtual IList<Invoice> Invoices { get; set; }
public virtual IList<OrdersAttachment> OrdersAttachments { get; set; }
public virtual IList<OrdersDueDate> OrdersDueDates { get; set; }
public virtual Header Header { get; set; }
}
public class Invoice : BaseItem
{
public virtual int Number { get; set; }
public virtual DateTime Date { get; set; }
public virtual double Amount { get; set; }
public virtual double VatRate { get; set; }
public virtual bool IsDisabled { get; set; }
public virtual bool IsSendMail { get; set; }
public virtual Order Order { get; set; }
public virtual IList<InvoicesDueDate> InvoicesDueDates { get; set; }
public virtual IList<InvoicesPayment> InvoicesPayments { get; set; }
}
I have a method in my program that build a "query" in a string variable.
private string GenerateQuery(FilterSubscription filterSubscription)
{
if (filterSubscription.FilterByOrder)
return "Account.Orders.Any()";
if (filterSubscription.FilterByInvoice)
return "Account.Orders.Any(Invoices.Any())"; //here is my problem
}
This is the call to the method
string query = GenerateQuery(filterSubscription)
var count = Session.Linq<Subscription>().Where(query).Count();
If I need to extract all accounts that have at least one Order is all OK.
But if I need to extract all accounts that have at least one Invoice I don't know how.
If I wrote
var count = Session.Linq<Subscription>().Where(s=>s.Account.Orders.Any(o=>o.Invoices.Any())).Count();
it works but if I use the string variable it doesn't.
It looks like you should return a delegate from GenerateQuery instead - something like:
private Expression<Func<Subscription, bool>> GenerateQuery(FilterSubscription filterSubscription)
{
if (filterSubscription.FilterByOrder)
return s => s.Account.Orders.Any();
if (filterSubscription.FilterByInvoice)
return s => s.Account.Orders.Any(o => o.Invoices.Any());
}
Then just update the query variable to be implicitly typed:
var query = GenerateQuery(filterSubscription);