I want to create a specific class to manage a collegion in my application.
For example, I have a Store and I have a list of customers in a collection, in this collection I have a customer that is the customer of the month, and some customers that got a prize to get a discount for some reason. Let's get to the code:
public class Store {
public ICollection<Customer> Customers { get; set; }
public Customer CustomerOfTheMonth
{
//get and set for customer of the month
}
public ICollection<Customer> DiscountCustomers
{
//get and set for customer of the month
}
public ICollection<Customer> GetAllCustomers
{
//get and set for customer of the month
}
}
But in my database, I only have two tables. Store, and Customer.
What I want to do is create a specific collection for the customer, to remove the logic from the Store and put in a specific class, after all, I don't feel that the logic belongs to neither of those classes.
I wans tomething like this:
public class Store {
internal CustomerCollection Customers { get; set; }
//get and set for the propertis, just delegating for the collection
}
public class CustomerCollection {
public ICollection<Customer> Customers { get; set; }
public ICollection<Customer> DiscountCustomers
{
//get and set for customer of the month
}
//get and set with logic to filter the collection
}
Is there away to create this mapping and keep with only two tables in the database? I want to make it transparent to the application. Sorry for the code problems, typed in stack overflow and didn't check the syntax.
don't need to create your business logic to your model classes. Separate your logic to upper level. Here are your model classes. It will create your relationships as you want
public class Store {
public vertual ICollection<Customer> Customers { get; set; }
//get and set for other propertis
}
public class Customer{
//get and set for other propertis
}
Create a repository or service layer to apply specific business logic ,
public ICollection<Customer> GetDiscountCustomers()
{
return dbContext.Customers.where(c=>c.discount=true).ToList()
}
if you want to load stores with customers at once you can use eager loading,
public ICollection<Store> GetAllStores()
{
return dbContext.Stores.Include("Customers").ToList()
}
Related
I am trying to Populate an object inside another object while avoiding two things:
Getting all the items in table
Making a separate call to the db for each item
Here is my code
Classes
public class Profile: BaseEntity
{
public Picture Picture { get; set; }
public string Name { get; set; }
}
public partial class Picture : BaseEntity
{
public string Name {get; set;}
}
Services
public class ProfileService : IProfileService
{
private readonly IRepository<Profile> _profileRepo;
private readonly IRepository<Picture> _pictureRepo;
public ProfileService(IRepository<Profile> profileRepo, IRepository<Picture> pictureRepo)
{
_profileRepo = profileRepo;
_pictureRepo = pictureRepo;
}
public IEnumerable<Profile> GetProfiles()
{
IEnumerable<Profile> profiles = _profileRepo.Table.ToList();
// I am guessing I would retrieve pictures here based off of picture
// ids that are in the profiles
// than I would populate the profiles with the pictures
}
}
Also in the database PictureId is a foreign key in Profile table.
If there is a relation between the objects then you should be able to just create a method in your repository to do:
public IEnumerable<Profile> GetAllProfilesWithPictures()
{
return your_context.Profiles.Include(x => x.Picture);
}
This will return all the profiles, along with their picture.
Not quite sure on what you mean when you say Getting all items in table.. If you want to limit what you get then you can put a where clause or whatever on the above statement.
What are some ways I can delete an item from a collection? (I am using MVC 4 and EF.)
As an example:
public class Birthday
{
public string Name { get; set; }
public virtual ICollection<Gift> Gifts { get; set; }
}
public class Gift
{
public string Name { get; set; }
public double Price { get; set; }
}
I'm using Editing a variable length list, ASP.NET MVC 2-style to create a dynamic list of Gifts.
The example is shows how to "Delete" a row. This will delete the row from the page and the correct Gifts are sent to the controller.
When I update the Birthday / Gifts everything new is updated properly, but anything deleted is still there.
So my question is what are some preferred ways to remove Gifts?
Two ways I've thought of already:
Get a Birthday from the DB and compare the Gifts removing as needed. I don't love this idea because it seems heavy handed.
Use WebApi / Ajax and delete the Gift from the list and the DB when the user pushes the delete link. I like this better than #1 but does this put too much business logic in the presentation layer?
I'm guessing that other people have had this similar problem and have a clever solution I haven't thought of yet.
Thanks in advance!
Make a Gifts api controller.
Let it have a Delete method accepting an Id of whatever type your Id is.
And do something like this in it:
public class GiftsController: ApiController
{
public void Delete(Guid Id)
{
var context = new MyContext();
var giftToDelete = context.Gifts.FirstOrDefault(g=> g.Id == Id);
if(giftToDelete != null)
{
context.Gifts.Remove(giftToDelete);
context.SaveChanges();
}
}
}
Make sure you make a DELETE request to this api in your JS delete function.
You may also replace the body of this method with some Service.DeleteGift(Id) if you're too concerned about doing things in the right place.
Like this:
public class ValuesController : ApiController
{
private List<string> list = new List<string>{"Item1","Item2","Item3","Item4","Item5"};
// DELETE api/values/5
public List<string> DeleteItem(int id)
{
list.Remove(list.Find((i => i.ToString().Contains(id.ToString()))));
return list;
}
}
I'm using Entity Framework Code First. The class i'm trying to create contains two collections (of the same type). I'm having problem recovering my respective collections.
My classes look like this:
public class Destination
{
public int DestinationId { get; set; }
public string Name { get; set; }
public List<Lodging> Lodgings { get; set; }
public List<Lodging> Lodgings2 { get; set; }
}
public class Lodging
{
public int LodgingId { get; set; }
public string Name { get; set; }
public Destination Destination { get; set; }
}
I created a new Destination, then I reopened (closed & opened) the database connection. When I retrieve the destination, my collections (dest.Lodgings and dest.Lodgings2) are null. How do I restore the respective collections? If my class only has one collection of a particular type, I could do the following:
var lodgings = context.Lodgings.Where(l => l.Destination.DestinationId == destId).ToList();
I can see that the relationships are maintained in the database schema (Destination_DestinationId1 and Destination_DestinationId2) but I don't seem to be able to get to them.
Any suggestion would be appreciated.
In addition to using Include (as you've discovered) (which loads the related data from the db at the same time the destination is retrieved) you can also retreive the lodgings after the fact. So if you query for the destination and then you want the lodgings, that's possible. One way is called explicit loading where you will use a Load method. The other is with lazy loading, which requires that your classes be set up a particular way and just the mere mention of the Lodgings property will trigger the call to the database to retrieve them.
there's a great blog post on the Ef team blog about the various ways to load related data with DbContext : http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx
hth
Julie
Ok, I'm pretty sure its just a matter of learning... but I have a very normalized db i'm working with so when I save to my product tbl I also have a productDollar tble and so on...
my question is in silverlight everything is async so How do I save a product get back its new id and use that as the productDollar.productID fk
so far with my other saves i just use the submitOperation in the callback of the submitchanges
and in there i check for iscompleted and do the next save and so on... and chain them together like that.
but I have 500 products I need to save (all at once)
so doing a foreach around my product object won't work because of the wonderful async
So what am I missing??? any help or pointers would be GREATLY appreciated
WCF RIA Services had this situation in mind when it was created. You can easily do it all in one SubmitChanges request and in one database transaction (depending on your DB and/or ORM). However, if you provide some more information about your objects (POCO, EF, etc.), you'll get a better answer.
That said, I'll take a wild guess at your objects as defined on the server.
public class Product
{
[Key]
public int? ProductID { get; set; }
// ... more properties ...
[Association("Product-ProductDollars", "ProductID", "ProductID", IsForeignKey = false)]
[Include]
[Composition]
public ICollection<ProductDollar> ProductDollars { get; set; }
}
public class ProductDollar
{
[Key]
public int? ProductDollarID { get; set; }
public int? ProductID { get; set; }
// ... more properties ...
[Association("Product-ProductDollars", "ProductID", "ProductID", IsForeignKey = true)]
[Include]
public Product Product { get; set; }
}
And your DomainService looks something like
public class ProductDomainService : DomainService
{
public IQueryable<Product> GetProducts()
{
// Get data from the DB
}
public void InsertProduct(Product product)
{
// Insert the Product into the database
// Depending on how your objects get in the DB, the ProductID will be set
// and later returned to the client
}
public void InsertProductDollar(ProductDollar productDollar)
{
// Insert the ProductDollar in the DB
}
// Leaving out the Update and Delete methods
}
Now, on your client, you'll have code that creates and adds these entities.
var context = new ProductDomainContext();
var product = new Product();
context.Products.Add(product);
product.ProductDollars.Add(new ProductDollar());
product.ProductDollars.Add(new ProductDollar());
context.SubmitChanges();
This results in one request sent to the DomainService. However, WCF RIA splits this ChangeSet containing the 3 inserts into 3 calls to your DomainService methods:
InsertProduct(Product product)
InsertProductDollar(ProductDollar productDollar)
InsertProductDollar(ProductDollar productDollar)
If your DomainService performs all inserts in one transaction, the ProductID can be correctly managed by your ORM.
I have a simple app that consists of:
Model
Items
Filter criteria applied to that list of items
Views
WelcomePage
MainItemsPage
FilterEditPage
I am using MVVM Light and Windows Phone 7
I currently have 3 ViewModels, one for each View. In the past I have had a single ViewModel which made the comunication which I am about to ask about very easy. However I wanted to go with the 3 seperate VMs as that seems to be the correct way.
The WelcomePage is able to set one of the Filter criteria before navigating to the MainItemsPage. The MainItemsPage is bound to an Items property that is exposed by its ViewModel. That ViewModel needs to have filtered that list depending on the current filter criteria. The FilterEditPage allows the user to edit the full criteria set of 4 variables. When the criteria is changed the Items collection used in the ViewModel for MainItemsPage needs to be refiltered.
The question is how I flow the Filter changes through the app. I know that MVVM has the concept of Messaging and the MVVM Light toolkit provides the Messenger class. However what I am struggling with is where does the responsibility lie for sending those messages?
Do the 3 VMs go to the Model whenever they need to work with the current Filter set?
Do all Filter updates go through the FilterEditViewModel and that in turn broadcasts a filter change message?
Do I go back to a single VM for all the Views?
I cannot see 1. working because something will need to trigger the VMs to go back to the Model
I know I can get 3. working right now with no problem. Is it that wrong?
TIA
Pat Long
I would put the shared current filter in the Model not the view model. You've got lots viewModels potentially on different pages or on the same page (consider a breadcrumb showing current selection and something else that needs to show a filter has been applied).
How about a singleton model for the Filter that view models can subscribe to?
Three VMs is the right way in your scenario. I suggest you to build a Parent/Child relation between you VMs. Since the the MainVM holds the ItemList, this is the place, where FilterChanges are applied. The FilterEditVM only receives the filter changes and than calls the MainVM, that it has to re-apply the filters.
The structure would be something like this:
public class WelcomePageVM
{
public WelcomePageVM()
{
this.FilterEditPageVM = new FilterEditPageVM(this);
this.MainItemsVM = new MainItemsVM(this);
}
public FilterEditPageVM FilterEditPageVM { get; private set; }
public MainItemsVM MainItemsVM { get; private set; }
public void SetInitialFilter1(object filter)
{
// the initial filter
this.FilterEditPageVM.Filter1Value = filter;
this.MainItemsVM.ApplyFilters();
}
}
public class FilterEditPageVM : ChildViewModelBase<WelcomePageVM>
{
public FilterEditPageVM(WelcomePageVM parent)
: base(parent) { }
public object Filter1Value { get; set; }
public object Filter2Value { get; set; }
public object Filter3Value { get; set; }
public object Filter4Value { get; set; }
public void FinishFilterChange()
{
this.Parent.MainItemsVM.ApplyFilters();
}
}
public class MainItemsVM : ChildViewModelBase<WelcomePageVM>
{
public MainItemsVM(WelcomePageVM parent)
: base(parent) { }
public List<object> ItemList { get; set; }
public void ApplyFilters()
{
// filter apply logic
}
}
public abstract class ChildViewModelBase<T>
{
T _parent;
public ChildViewModelBase(T parent)
{
this._parent = parent;
}
public T Parent { get { return _parent; } }
}
Here you can access all viewmodels, which is okay because you stay in the "controller" level.