Entity Framework 4 Updating child collections - entity-framework-4

I have created some basic sample code below. I am using the entity framework. I have a Parent object that has a collection of Children. I initally set up three children. When I am Updating the children I am removing one (John) and adding one (Sarah) the other two (Mary & Anne) remain the same. Is there any way to do this easily taking into account the database behind?
public class test
{
public test()
{
Parent father = new Parent();
father.Children.Add(new Child() { FirstName = "Mary" });
father.Children.Add(new Child() { FirstName = "Anne" });
father.Children.Add(new Child() { FirstName = "John" });
SaveEntityFramework();
}
public void UpdateChildren
{
Parent father = EntityFramework.GetParentByID(1);
// Remove John
father.Children.Remove(new Child() { FirstName = "John" });
// Add Sarah
father.Children.Add(new Child() { FirstName = "Sarah" });
// Update or do Nothing Mary & Anne
SaveEntityFramework();
}
}
public class Parent
{
public string Name { get; set; }
public List<Child> Children;
}
public class Child
{
public string FirstName { get; set; }
}

Did you add the father to your EntityFramework context? You're just creating it, adding the 3 children and then saving!
public test()
{
Parent father = new Perent();
EntityFramework.Parents.Add(father);
// Add children
SaveEntityFramework();
}
Also, make sure what you get when you do EntityFramework.GetParentByID(1); you're getting the Parent you're looking for.
Hope this helps ;)

Related

What is a good way to insert an entity with dependencies using TableController?

I am struggling to insert a new entity which references other existing entities using table controller in azure mobile services.
This is my set up:
Entities:
public class EntityB : EntityData
{
public EntityA Parent { get; set; }
//some data
}
public class EntityA : EntityData
{
//some data
}
Dtos:
public class DtoEntityB : EntityData
{
public DtoEntityA Parent { get; set; }
//some data
}
public class DtoEntityA : EntityData
{
//some data
}
Controller:
public class Controller : TableController<DtoEntityB>
{
public virtual async Task<DtoEntityB> Post(DtoEntityB entity)
{
return await InsertAsync(entity);
}
}
Mapper:
AutoMapper.Mapper.Initialize(cfg =>
{
// use other mapper
cfg.CreateMap<DtoEntityB, EntityB>();
cfg.CreateMap<EntityB, DtoEntityB>();
cfg.CreateMap<DtoEntityA, EntityA>();
cfg.CreateMap<EntityA, DtoEntityA>();
}
EntityA exists already, so I make a client call which results in JSON sent to the Post method. Then everything works fine until EF tells me that there is already an EntityA with id = 317238621736.
{
"EntityA" : {
"Id" : "317238621736"}
}
I am looking for a generic solution for this problem (right now I do direct operations on the context (attach) for every existing reference, combing this with Mapper makes this approach unsustainable.

Mvc - store a list in session and then retrieve its value

Hello I'm trying to make a simple online magazine and I got to the part where when the user clicks addtoCart button
My model Cart holds two properties - product and Quantity
public class Cart
{
public ProductLanguages Product { get; set; }
public int Quantity { get; set; }
}
So in my basketViewModel (class) inside my AddProductToCart method I add the product, the details for which I get from database in property of List.
So I can't figure out this issue: Somewhere in the control I should save this list in a Session and if the user adds more products the next time I should get the list from this session. If someone can give me an example of controler with an index action that can do this I would be really thankful.
public class BasketViewModel
{
private readonly IProductLanguagesRepository prodlanRepository;
public List<Cart> listProductsinBasket { get; set; }
public BasketViewModel() : this(new ProductLanguagesRepository())
{
}
public BasketViewModel(IProductLanguagesRepository prodlanRepository)
{
this.prodlanRepository = prodlanRepository;
}
public void AddProductToCart(int id,int quantity)
{
ProductLanguages nwProduct = prodlanRepository.GetProductDetails(id);
if (nwProduct != null)
{
Cart cr = new Cart();
cr.Product = nwProduct;
cr.Quantity = quantity;
listProductsinBasket.Add(cr);
}
Store:
HttpContext.Session["list"] = new List<object> { new object(), new object() };
Retrieve:
var list = HttpContext.Current.Session["list"] as List<object>;

Create object with list of properties and pass it to Controller

Perhaps there is an easy solution for my problem but I simply cannot seem to find it. I have read lots of tutorials about Knockout so I get the basics but I ask this question because my entity-structure is a bit more complicated than a person with a name and a list of friends which may or may not be on Twitter (Video on Channel9: Helping you build dynamic JavaScript UIs with MVVM and ASP.NET). Here's my situation:
I have a class PersonnelClass with this basic structure:
[Serializable]
//The interface is for the implementation of 'Name' and 'Description'
public class PersonnelClass : IPersonnelClassOrPerson
{
public PersonnelClass() : this(Guid.NewGuid(), "", "") { }
public PersonnelClass(Guid id, String name, String description = null)
{
if (id == Guid.Empty) { throw new ArgumentNullException("id"); }
Id = id;
Name = name;
Description = description;
Properties = new PropertyCollection();
}
public Guid Id { get; private set; }
public String Name { get; set; }
public String Description { get; set; }
public PropertyCollection Properties { get; private set; }
}
The PropertyCollection class and associated AbstractProperty class look like this:
[Serializable]
public class PropertyCollection: List<AbstractProperty> { }
[Serializable]
public abstract class AbstractProperty: IEntity, IProperty
{
public AbstractProperty(String name, String description = null) : this(Guid.NewGuid(), name, description) { }
public AbstractProperty(Guid id, String name, String description = null)
{
if (id == Guid.Empty) { throw new ArgumentNullException("id"); }
if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); }
Id = id;
Name = name;
Description = description;
}
public Guid Id { get; private set; }
public String Name { get; private set; }
public String Description { get; private set; }
}
In my Controller, I create an instance of a PersonnelClassViewModel that has this structure:
public class PersonnelClassViewModel
{
public PersonnelClass PersonnelClass { get; set; }
public List<AbstractProperty> Properties { get; set; }
}
I fill this viewmodel with a new PersonnelClass and two test-properties to pass to my View like this:
var properties = new List<AbstractProperty>
{
new TextProperty("prop1", "descr1"),
new TextProperty("prop2", "descr2")
//TextProperty is derived from AbstractProperty
};
var vm = new PersonnelClassViewModel { Properties = properties };
return View(vm);
I get everything in my View as I wanted. From the View I want to create a new PersonnelClass with a set of selected properties. I have the fields for Name and Description and to add the properties I have a ListBox with the properties that already exist (for demo-purpose they came from the controller now). Through a bit of Knockout JavaScript code I can select items from this list and populate an HTML select-control () with the selected properties to add to the PersonnelClass. This all works fine, until I want to build up an object to pass back to the Controller and create the PersonnelClass.
My question is: what Knockout JS code is needed to build up this object and pass it to the Controller by submitting the form and in my Controller how should I receive this object, meaning: what type of object should this be (PersonnelClass, PersonnelClassViewModel, ...) ?
If any more info/code is needed, please do ask. Thanks in advance!
Update after answer of 'B Z':
I followed a few more of Steven Sanderson's tutorials about this to be sure I understand this, especially the one you provided in your answer. Now I have following code in my View to start with:
var initialData = #Html.Raw(new JavaScriptSerializer().Serialize(Model));
var viewModel = {
personnelClassViewModel : ko.mapping.fromJS(initialData),
properties : personnelClassViewModel.Properties,
selectedProperties : ko.observableArray([]),
addedProperties : ko.observableArray([])
};
ko.applyBindings(viewModel);
The variable 'initialData' contains the values I expect it to have but then I get the following error:
Microsoft JScript runtime error: 'personnelClassViewModel' is undefined
I have no clue anymore. Can anyone help me fix this?
Steven Sanderson has an example of how to to work with variable length lists and knockoutjs
http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/
Having said that, I think your problem isn't so much on the knockout side and more on the how to databind the data correctly on the server side. In the link above, Steven uses a FromJson attribute to model bind which you may find useful...
HTH

S#arp Architecture Fluent mapping for self referencing entity (Tree structure)

I've come up against a problem in converting my Fluent NH mapping to Sharp Architecture. I like the platform for it's ease, however it seems to handle entity mappings slightly differently to pure Fluent NH.
I have a Entity 'Category' that is a simple tree structure. I have to override the auto-mapping as there is a M:M property that I need to add in (not included in code below).
When I create tests on the repository, the GetAll method returns all Categories as it should, however the Children property just infinitely loops itself. i.e. the list of children for each category only contains itself, in and unending loop.
/// The Entity ///
public class Category : Entity
{
public Category()
{
InitMembers();
}
/// <summary>
/// Creates valid domain object
/// </summary>
public Category(string name)
: this()
{
Name = name;
}
/// <summary>
/// Creates valid domain object
/// </summary>
public Category(string name, int depth)
: this()
{
Name = name;
Depth = depth;
}
private void InitMembers()
{
Children = new List<Category>();
}
[DomainSignature]
[NotNullNotEmpty]
public virtual string Name { get; protected set; }
[DomainSignature]
public virtual int Depth { get; protected set; }
public virtual Category Parent { get; set; }
public virtual IList<Category> Children { get; private set; }
public virtual void AddChild(Category category)
{
category.Parent = this;
Children.Add(category);
}
}
/// The Mapping ///
public class CategoryMap : IAutoMappingOverride<Category>
{
public void Override(AutoMap<Category> mapping)
{
mapping.Id(x => x.Id, "CategoryId")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
mapping.Map(x => x.Name).WithLengthOf(50);
mapping.Map(x => x.Depth);
mapping.HasMany<Category>(x => x.Children)
.Inverse()
.Cascade.All()
.KeyColumnNames.Add("Parent_id")
.AsBag();
}
}
/// The Data Repository Tests ///
[TestFixture]
[Category("DB Tests")]
public class CategoryRepositoryTests : RepositoryTestsBase
{
private readonly IRepository<Category> _repository = new Repository<Category>();
protected override void LoadTestData()
{
CreatePersistedCategory("Root 1");
CreatePersistedCategory("Root 2");
CreatePersistedCategoryWithChildren("Level 1", "Level 2", "Level 3");
}
[Test]
public void CanGetAllCategories()
{
var categories = _repository.GetAll();
categories.ShouldNotBeNull();
categories.Count.ShouldEqual(5);
}
[Test]
public void CanGetCategoryById()
{
var category = _repository.Get(1);
category.Name.ShouldEqual("Root 1");
category.Depth.ShouldEqual(1);
}
[Test]
public void CanGetCategoryChildren()
{
var category = _repository.Get(3);
category.Name.ShouldEqual("Level 1");
category.Depth.ShouldEqual(1);
category.Children.ShouldNotBeNull();
category.Children.Count.ShouldEqual(1);
category.Children[0].Name.ShouldEqual("Level 2");
category.Children[0].Depth.ShouldEqual(2);
category.Children[0].Children.ShouldNotBeNull();
category.Children[0].Children.Count.ShouldEqual(1);
category.Children[0].Children[0].Name.ShouldEqual("Level 3");
category.Children[0].Children[0].Depth.ShouldEqual(3);
}
private void CreatePersistedCategory(string categoryName)
{
var category = new Category(categoryName, 1);
_repository.SaveOrUpdate(category);
FlushSessionAndEvict(category);
}
private void CreatePersistedCategoryWithChildren(string category1, string category2, string category3)
{
var cat1 = new Category(category1, 1);
var cat2 = new Category(category2, 2) { Parent = cat1 };
var cat3 = new Category(category3, 3) { Parent = cat2 };
cat1.AddChild(cat2);
cat2.AddChild(cat3);
_repository.SaveOrUpdate(cat1);
FlushSessionAndEvict(cat1);
}
}
Managed to work it out, after much Mapping tweaking. The Auto-mapping stuff although very cool requires some understanding. RTFM for me...
Right you are, I hadn't yet discovered or understood the Auto-mapping conventions: TableNameConvention, PrimaryKeyConvention, and specifically HasManyConvention. The default S#arp code likes to pluralise its database tables, and have Id columns with the table name prefixed, i.e. CategoryId.
I don't like to pluralise, and I like consistent Id columns, 'Id' suffices. And my foreign key references were different style to, I like Category_id.
public class HasManyConvention : IHasManyConvention
{
public bool Accept(IOneToManyCollectionInstance oneToManyPart)
{
return true;
}
public void Apply(IOneToManyCollectionInstance oneToManyPart)
{
oneToManyPart.KeyColumnNames.Add(oneToManyPart.EntityType.Name + "_id");
}
}
public class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityInstance id)
{
return true;
}
public void Apply(IIdentityInstance id)
{
id.Column("Id");
}
}
However now this all works a treat but I now have a problem with Many-to-many mappings. It seems S#arp doesn't quite support them yet. My mapping overrides don't seem to work, nothing gets inserted into my mapping table in the database.
See: S#arp Architecture many-to-many mapping overrides not working
I was not able to solve this using fluent conventions and from what I have seen searching around this currently can't be done using conventions. Fluent assumes that a self-referencing tree like this is many-to-many, so in your case I assume you are trying to map a many-to-many relationship and so there should be no problem.
In my case I needed to map it as many-to-one (for a strict hierarchy of nested comments and replies). The only way I could figure out to do this was setting an override for the parent-child class to map that relationship. Fortunately it is very easy.
I would love to know if there is a way to successfully map many-to-one like this with conventions though.

Db4o Tree structure C#

I'm new to db4o and i'm trying to figure out if it's possible to do the following:
public class Page
{
public Guid ID {get;set;}
public Page Parent {get;set;}
public IList<Page> Children {get;set;}
public String Name {get;set;}
public String Depth {get;set;}
}
When I save the page i have it's parent only.
IE
Page p1 = new Page() {
ID = Guid.NewGuid(),
Name = "p1",
Parent = null
};
Page p2 = new Page() {
ID = Guid.NewGuid(),
Name = "p2",
Parent = p1
};
Page p3 = new Page() {
ID = Guid.NewGuid(),
Name = "p3",
Parent = p1
};
When i load up p1 is there anyway to populate the two children??
Db4O will load also the collection of children as soon as you load p1 from the datastore, so yes it's possible...
Well the easiest way to do this is actually to just use the property-call to wire things up. Like this:
public class Page
{
private Page _parent;
public Page Parent {
get{return _parent;}
set{
value.Children.Add(this);
this._parent = value;
}
}
public IList<Page> Children {get;set;}
// omitted the the other properties
}
As soon as you assign a Page-instance to Page.Parent, the Page is in the Page.Children-property.
Is this a solution?
Not sure about DB4O but you should consider using the IComposite pattern for this.

Resources