Using Entity Framework and having the following class:
public class TestClass{
[Key]
public int id {get; set;}
public int foreignId {get; set;}
[ForeignKey("foreignId")
public MyObject myObject {get; set;}
}
With this class I want to save the "TestClass" but the entity framework first tries to save/create the "myObject" that doesn't need to get saved because it's only a reference.
In some forums (enter link description here) I read that I has to set the myObject explicitely to "null" before saving, but in my opinition this is quite annoying.
So I want to ask if there is any annotation or something like "IgnoreOnSave" that I can add to the myObject?
[ForeignKey("foreignId", "ignoreOnSave")]
public MyObject myObject {get; set;}
Update
[NotMapped] did it for me:
[NotMapped]
[ForeignKey("foreignId")]
public MyObject myObject {get; set;}
With this attribute I can load the object with the foreign sub object, but on saving the subObject "myObject" is ignored. I only need to assure in code, that the ID of "myObject" is copied to the foreign-key-property of the main object.
Additionally (I'm creating a Web-Api-Solution) I added a [JsonIgnore] to the foreign-key-property so that I have clean interfaces.
Update
Using [NotMapped]leads to that the linq expression ".include" can't be used for the respective properties anymore.
Related
How to deserialize to an object of this type using NewtonSoft JSON? The structure contains the property type variable, but with the use of NewtonSoft based on this structure, this property would be another class.
The following code example:
public class RootProduct
{
public Package Package {get; set;}
}
public class Package
{
//Package has a property in which the class type should be changed in order to deserialize
public Package_id ThisValueIsVariable {get; set;}
}
public class Package_id
{
public string product_name {get; set;}
}
In the data query of this package it is necessary to send the Package_id, the return of this query is received as in the structure below, the field "Package_id" (in return JSON) is this code sent in the query.
Returned JSON:
"Package": {
"Package_id": { //This is the value that changes according to the value passed in the query to JSON
"package_name": "my product name"
}
}
"Package": {
"SecondPackage_id": { //This is the value that changes according to the value passed in the query to JSON
"package_name": "my product name"
}
}
"Package": {
"ThirdPackage_id": { //This is the value that changes according to the value passed in the query to JSON
"package_name": "my product name"
}
}
UPDATE:
In the above code only the first product will be deserialized, because there is only one class with the name "package_id", and the second and third JSON items will not deserialize using JsonConvert.Deserialize because the SecondPackage_id class does not exist Consecutively.
The solution depends if you know the name before runtime or not.
When you know the possible names before hand you can create a separate property for each type in the Package class as follows:
public class Package
{
public Package_id FirstPackage {get; set;}
public Package_id SecondPackage {get; set;}
public Package_id ThridPackage {get; set;}
}
Other properties should reserialize to null.
When you do not know the possible ids at runtime then you are actually receiving
a key value pair. Because they key is different per object, there technically could be multiple (even if in you case it might only always be one). Use a dictionary to get (multiple) named objects from JSON
public class RootProduct
{
//No package class needed
public IDictionary<string, Package_id> Package {get; set;}
}
public class Package_id
{
public string product_name {get; set;}
}
Ive searched for this for few days now and cant seem to get anything to work, I am using c# MVC Entity Framework with Automapper and im trying to achieve the below ViewModels (mainly LostDocumentVM) to be mapped from my database, all other properties will be set in controllers.
Here is my ViewModels...
DocumentVM
{
Public Enum.HistoricType HistoricType {get;set;}
Public DocumentChildVM Document { get; set;}
}
DocumentChildVM
{
Public bool ShowHistoricLink {get;set;}
Public IEnumerable<ListDocumentVM> DocumentsToReview {get;set;}
}
ListDocumentVM
{
Public int Id {get;set;}
Public string Name {get; set;}
Public DateTime? ReviewDate {get;set;}
}
I initialise the DocumentVM like this...
DocumentVM documentVM = DataContext.SystemUser.Where(x=>x.SustemUserID==LoggedOnUserID).Project().To<DocumentVM>().SingleOrDefault();
And my mapping is like this...
Mapper.CreateMap<SystemUser,DocumentVM>()
.ForMember(dest=>dest.Document.DocumentsToReview, opt=>opt.MapFrom(src=>src.Documents.Where(x=>x.DocumentType == Enum.DocumentType.Assessment));
Im new to AutoMapper and struggling to get more advanced mappings to work.
Yes, your ForMember member must refer to a member on the destination type, and yours is referring to a member on the child type. Instead, you'll need to create an AfterMap function that fills in this information on that child entity.
It's not difficult, but you have a bit of a strange set up where a child object Document has a property DocumentsToReview from another property on the parent DocumentVM:
documentVM.Document.DocumentsToReview =
src.Documents.Where(doc => doc.DocumentType == Enum.DocumentType.Assessment);
When you have to shuffle data between sibling/nephew members, it gets a little more challenging.
To do this with AfterMap:
Mapper.CreateMap<SystemUser, DocumentVM>()
.AfterMap((src, dest) => dest.Document.DocumentsToReview =
src.Documents.Where(doc => doc.DocumentType == Enum.DocumentType.Assessment));
In a situation where an EntitySet is being queried (in, say, a many-to-many relationship), is it possible to access the parent object?
e.g
Thing thing = db.Things.First();
Widget widget = thing.Widgets.First();
// Let's assume that Widgets can have many things as well
// (i.e. widget.Things is possible)
widget.ParentThing // would return the same instance of thing used above
Is that possible?
is it possible to access the parent object
With a many-to-many there really isn't a "parent" - there are multiple related objects. A many-to-many is usually modeled with navigation properties:
public class Thing
{
public int ID {get; set;}
public virtual IEnumerable<Widget> Widgets {get; set;}
}
public class Widget
{
public int ID {get; set;}
public virtual IEnumerable<Thing> Things {get; set;}
}
If your model doesn't have such properties then an alternative is to go back to the context (or back to the db if you don't have the context anymore):
var relatedThings = db.Things
.Where(t => t.Widgets.Any(w => ID == widget.ID));
I'm having huge difficulties getting my navigation properties to work in EF Code First. As an abstracted example, I have:
public class Parent{
public int ParentID {get; set;}
public virtual List<NamedChild> Children {get; set;}
public Parent(){}
public void Init(int ParentID, List<UnnamedChild> Children){
this.ParentID = ParentID;
this.Children = Children.ConvertAll(x => new NamedChild(x, ""));
}
}
public class NamedChild{
public int ChildID {get; set;}
public string Name {get; set;}
public NamedChild(UnnamedChild c, string Name){
this.ChildID = c.ChildID;
this.Name = Name;
}
}
public class UnnamedChild{
public int ChildID {get; set;}
public UnnamedChild(int ChildID){
this.ChildID = ChildID;
}
}
and then later...
List<UnnamedChild> children = GetChildrenFromSomewhere();
Parent p = db.Parents.Create();
p.Init(1, children);
db.Parents.Add(p);
db.SaveChanges();
Now if I'm debugging I can look into the current DbSet and it shows that there is 1 Parent, and its "Children" property is set to a List of 2 NamedChild. This is good, this is what it should be. However, if I stop the program and re-run it, when I look in the DbSet there is still 1 Parent, but its "Children" property has been set to null.
In summary, immediately after saving it the values are right, but as soon as I re-load the DB Context those values are missing (nulls). I am running the most recent EF with LazyLoading enabled.
It should be noted that if I use .Include(), it will populate those null values with the proper NamedChild list, but I need this to work with LazyLoading.
I think EF is probably unable to create a proxy for NamedChild objects, and can't perform any lazy loading as a result.
One of the requirements for creating a proxy class is that your POCO must have a public/protected constructor without parameters.
This may solve your problem:
public class NamedChild
{
public int ChildID {get; set;}
public string Name {get; set;}
protected NamedChild() {}
public NamedChild(UnnamedChild c, string Name)
{
this.ChildID = c.ChildID;
this.Name = Name;
}
}
I believe you already meet all the other requirements for lazy loading proxies.
Full Requirements here:
http://msdn.microsoft.com/en-us/library/vstudio/dd468057%28v=vs.100%29.aspx
Although I don't think it should technically matter, I've noticed that EF seems to prefer ICollections to other list/array types. Try:
public virtual ICollection<NamedChild> Children {get; set;}
Also, I'm a little confused about what you're trying to achieve with your custom constructors. It seems that all you're doing is initializing the properties on the instance. If that's the case, a custom constructor is not needed. Just use the class initialization syntax:
x => new NamedChild { ChildId = x.ChildId, Name = "" }
Using BsonClassMap, is it possible to map a domain object reference while keeping the domain object assembly persistent ignorant (changing the public A Reference { get; set; } property to public MongoDBRef Reference{ get; set; } in the sample class B below is not acceptable).
For this case, the referenced object is not a part of the same aggregate, and should not be stored as a nested document.
Is it possible map two domain objects in a relationship like this:
public class A
{
public Guid Id {get; private set; }
}
public class B
{
public Guid Id { get; private set; }
public A Reference { get; set; }
}
Into the following document structure:
// Collection for class A
{ _id: "11111111-1111-1111-1111-111111111111" }
// Collection class B
{
_id: "22222222-2222-2222-2222-222222222222",
reference_id: "11111111-1111-1111-1111-111111111111"
}
The mapping may look like:
BsonClassMap.RegisterClassMap<A>(cm =>
{
cm.MapIdProperty(c => c.Id)
.SetIdGenerator(new GuidGenerator())
.SetRepresentation(BsonType.String);
}
BsonClassMap.RegisterClassMap<B>(cm =>
{
cm.MapIdProperty(c => c.Id)
.SetIdGenerator(new GuidGenerator())
.SetRepresentation(BsonType.String);
// How do I map the B.Reference to a manual reference (like
// the sample doc structure above) or possibly as a DBRef?
}
So, without changing the model, how do I map the Reference property to object A, from object B as either a DBRef or as a manual references (as in my sample document structure above)?
Is this possible using BsonClassMap? Or in order to use BsonClassMap and keep my domain assembly persistent ignorant, do I need to change the model to something like:
public class A
{
public Guid Id {get; private set; }
}
public class B
{
public Guid Id { get; private set; }
public Guid ReferenceId { get; set; } // Don't reference the object directly,
// just store the Guid to the
// referenced object.
}
I posed this same question to the mongodb-csharp user group and got a response from craiggwilson:
You'll need to change your ReferenceProperty to ReferencePropertyId. We do not support lazy-loading (or eager-loading) of referenced documents.
Since A is not the aggregate for B, then this actually makes more sense when discussing in these terms. Generally, it is unnecessary for a referenced aggregate (B) to be loaded in order to process the referencing aggregate (A). It might be that you do indeed need some information from B. In this case, think about denormalizing a little and creating a true entity (BSummary) whose aggregate is A. This would make sense if some of the summary information is immutable or changes infrequently.