I'm working on a cinema application which allows users to surf through movies, cinema places and allows them to buy or reserve tickets. If a user reserved a ticket online, then the ticket must be activated in 12 hours by sellerperson who also uses the same program. I need to show the ticket informations on grid and need to make editable. Here's my database classes that must be included in query and have relationship with Sale class. (I want to select objects from Sale class which includes ti's related classes: Ticket, customer, movie, status and saloon infos.
Sale Class:
public class Sale
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[ForeignKey("CustomerId")]
public virtual Customer Customer { get; set; }
public int CustomerId { get; set; }
[ForeignKey("StatusId")]
public virtual Status Status { get; set; }
public int StatusId { get; set; }
public virtual Seller Seller { get; set; }
public DateTime SellDate { get; set; }
public double Price { get; set; }
[ForeignKey("TicketID")]
public virtual Ticket Ticket { get; set; }
public int TicketID { get; set; }
}
Ticket Class:
public class Ticket
{
public Ticket()
{
Seats = new List<Seat>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[ForeignKey("MovieId")]
public virtual Movie Movie { get; set; }
public int MovieId { get; set; }
public virtual List<Seat> Seats { get; set; }
public virtual TimeSpan SeanceTime { get; set; }
public bool IsActive { get; set; }
public DateTime BuyDate { get; set; }
[ForeignKey("SaloonId")]
public virtual Saloon Saloon { get; set; }
public int? SaloonId { get; set; }
public string TicketNumber { get; set; }
}
Customer Class:
public class Customer
{
public Customer()
{
Sales = new List<Sale>();
CreditCards = new List<CreditCard>();
}
[Key]
public int UserID { get; set; }
public virtual List<Sale> Sales { get; set; }
public virtual User User { get; set; }
[DataType(DataType.CreditCard)]
public virtual List<CreditCard> CreditCards { get; set; }
}
User Class:
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
Status Class(Holds info of tickets. Bought or reserved.)
public class Status
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public bool IsRez { get; set; }
public bool IsBuy { get; set; }
public bool IsCancel { get; set; }
public bool IsPaid { get; set; }
}
Saloon Class:
public class Saloon
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
public double salePrices { get; set; }
}
Movie Class:
public class Movie
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
}
I can't edit because in my select query I'm using anonymous type for selection. My query code:
var Source = entities.Sales.Where(w => w.Ticket.Saloon.CinemaPlace.ID == seller.CinemaPlace.ID).Select(s => new
{
CustomerName = s.Customer.User.Name,
CustomerSurname = s.Customer.User.Surname,
SalePrice = s.Price,
s.Status.IsBuy,
s.Status.IsCancel,
s.Status.IsPaid,
s.Status.IsRez,
MovieName = s.Ticket.BuyDate,
s.Ticket.Movie.Name,
SaloonName = s.Ticket.Saloon.Name,
s.Ticket.SeanceTime,
s.Ticket.TicketNumber
}).ToList();
RezervationsGrid.DataSource = Source3;
But in the grid, the datas couldn't be edited. Then I tried to join every single table using Linq to Entities queries but it didn't help either. Is there a way make a datasource from my related objects that allows edit option in grid? Thanks.
Anonymous types (those that you can declare via the new operator in the Select method) cannot have writable properties in .NET. That's why the grid is not editable. To take advantage of in-place editing, you need to instantiate objects of a real CLR type.
For this, you can declare a special ViewModel class with public properties that you should populate with values in the Select method using object initializer.
.Select(s => new SaleViewModel() {
CustomerName = s.Customer.User.Name,
SalePrice = Price
})
Note that you should not move the property initialisation logic to the ViewModel constructor to use it this way:
.Select(s => new SaleViewModel(s))
The object initialiser is the expression tree, which Entity Framework can translate into an SQL query. The constructor is just a method reference, so Entity Framework will reject such an expression. If you would like to use this approach, you will need to call the ToList method before the Select.
SaleViewModel can have the method accepting the DbContext class to save changes.
You also can select the Sale instances and use complex property paths in columns' field names (such as "Customer.User.Name"). This can probably help you to simplify the saving logic, as you will not need to find a model specific to a certain view model and copy modified property values.