Suppose i have the following class.
public class Location
{
public Id { get; set;}
public Name { get; set;}
}
And i have a WebPage called Location that looks like this.
txtId
txtName
txtCountStaffWorkersAtLocation
txtCountVehiclesAtLocation
txtCountNonStaffWorkersAtLocation
txtCountetc
listViewPersonnel
listViewVehicles
Right now i'm calling a repository to display the Location fields on the view, but i'm confused as to what the correct method would be to get and display the data for the other fields. They obviously have very little to do do with the Location Class.
Do i put the Counts in the Location Class and fill them in when i set up the Location class from the database?
Do i have a struct object somewhere that has just has these count fields?
What do you guys normally do with object being displayed on a page that have very little to do with the Domain Object?
Thanks
I'd recommend implementing StaffPersonnel, NonStaffPersonnel, and Vehicles as properties on the Location object, with each of those properties returning a collection of the associated objects. Then for the counts, you could properties from a location object as follows:
loc.Vehicles.Count
loc.StaffPersonnel.Count
loc.NonStaffPersonnel.Count
Related
I get data from my database (Firebase database). This is a document with several data, including a Array with GeoPoint fields.
var documents = await CrossCloudFirestore.Current .Instance .Collection("Activity") .GetAsync();
My object is defined like this in my Model class: public class Activity { public object elapsedTime { get; set; } public object positions { get; set; } ...... }
It works. I can have the data on my Activity class.
However, I would like to know how I can access this data because foreach loops do not work for object types. Maybe I need to redefine my Activity Class ?
Thx :=)
Edit :
You can see here my firebase :
And then the result of the request :
In your scenario , the property is dynamic for each object , I would suggest you deserialize the root level as a dictionaryand then get the data you want .
Items = JsonConvert.DeserializeObject<Dictionary<string, YourClass>>(content).Values.ToList()
Oh before this, Newtonsoft plugin is required .
Refer to
Deserialize JSON into readable format
It works ! :)
To do it, I defined Array (from firestore) as IEnumerable on my C# class, with the same name from firestore to c#.
And then, here is my query and the line to get my objects converted.
I have two entities:
//The master table/entity
[TABLE("POSITIONS")]
public class Position{
[Key,Column("POSITIONID")]
public int PositionId{get;set;}
[Column("POSITIONNAME")]
public string PositionName{get;set;}
}
//The detail table/entity
[TABLE("SLAVE_POSITIONS")]
public class SlavePosition{
[Key,Column("MASTERPOSID",Order=0)]
public int MasterPosId{get;set;}
[KEY,Column("SLAVEPOSID",Order=1)]
public string SlavePosId{get;set;}
[ForeignKey("MasterPosId")]
public virtual Position MasterPosition {get;set;}
[ForeignKey("SlavePosId")]
public virtual Position SlavePosition {get;set;}
}
In the SlavePosition, as you can see, there two columns over which this entity is in FK relationship with Position. This layout works great. Now I also need to add this collection property to Position entity:
public virtual ICollection<SlavePosition> SlavePositions{get;set;}
But apparently EF gets confused and I get {"ORA-00904: \"Extent1\".\"Position_PositionId\": invalid identifier"} error.
If I declare it like this:
[ForeignKey("SlavePositionId")]
public virtual ICollection<SlavePosition> SlavePositions { get; set; }
and then fetch a Position with PositionId =1 like this:
Position pos= dbContext.Positions.SingleOrDefault(x=>x.PositionId==1);
I get no error, but I get SlavePOsitions count 0, when it should be 5 because in the database I have 5 rows in the detail table. I am able to confirm this by running the below code:
IEnumerable<SlavePositions> slavePositions= dbcontext.SlavePositions.Where(x=>x.MasterPositionId==1);
I get five SlavePosition.
What should be the correct attribute for this collection property?
I finally figured it out. My mistake was in the referenced dependent property name. Instead of SlavePositionId I should put MasterPositionId.
This makes sense, because the Position entity acts as a master table and in real world Foreign Key relationship is set up on detail tables, not master ones. As there's no property in the dependent entity that has the same name as the PK in the master entity and there're more than one properties that have Foreignkey to the same master entity, EF needs more information.By specifying ForeignKey("MasterPositionId") to the ICollection navigation property, I instruct EF that Dependent end point property should be considered MasterPositionId. So I changed this
[ForeignKey("SlavePositionId")]
public virtual ICollection<SlavePosition> SlavePositions { get; set; }
to this
[ForeignKey("MasterPositionId")]
public virtual ICollection<SlavePosition> SlavePositions { get; set; }
In fact the former one itself is not wrong either, it just does not fit in this situation. But if I wanted to have a collection for MasterPositions this would fit perfectly fine.
I have a one to many relationship as outlined below. In some parts of the business layer there are queries of the Item table and in others the Client table (as well as its Items). LazyLoading and ProxyCreation are both false, reference loop handling is set to ignore.
public class Client {
public virtual ICollection<Item> Items { get; set; }
public string Name {get;set;}
}
public class Item {
public virtual Client TheClient {get;set;}
public string ItemProp {get;set;}
// another 10 properties or so
}
myitems = dbContextScopeX.Items.Include(x => x.Client).ToList();
The view has a list of items with the need to show the Client's Name (in my example). I am looking for item.Client.Name ultimate, however when myitems gets queries/serialized it contains:
myitems.Client.Items
If I set the attribute [JsonIgnore] on the Client's Item property it never comes through the graph which I need it to in other places. Is there a way to get myItems.Client.Name without having to get myitems.Client.Items in the query or without having to create an anonymous projection for the Item array?
Project the Item properties you want (be they simple or complex type) along with just the Client name into an anonymous type and serialize that.
myitems = dbContextScopeX.Items.Include(x => x.Client)
.Select(i=>new {
ItemProp = i.ItemProp,
ItemCollection = i.ItemCollection,
...
ClientName = i.Client.Name
}).ToList();
Only caveat is you have to do some manual work if you want to deserialize this back into entities.
In my one of the view I add a dropdown and I bind this drop down with my database like this..
public ActionResult PostMarks()
{
JoinMod std = new JoinMod();
std.Drp_bind = (from nm in db.TbStudent
select new SelectListItem
{
Text = nm.StudentName,
Value = SqlFunctions.StringConvert((double)nm.StudentId).Trim()
}).ToList<SelectListItem>();
return View(std);
}
Here is the dropdownlist in my view
<p>StudentName</p>
#Html.DropDownList("StudentName",Model.Drp_bind,"Select")
And on Post I am trying to save the data into the database like this
[HttpPost]
public ActionResult PostMarks(Marks marks)
{
db.TbMarks.Add(marks);
db.SaveChanges();
return RedirectToAction("ShowAllMarks");
}
Now when I check my database after save data in database the Id save in the database is zero from the dropdownlist. Please experts help me to solve this issue
You should be using #HTML.DropDownListFor, specifying a lambda that indicates which property in your model you want to bind the list's selected value to on the POST.
Given a view model like so:
public class MarksViewModel
{
public Marks Marks { get; set; }
public IEnumerable<SelectListItem> Drp_bind { get; set; }
}
The drop down list in the CSHTML can be declared like so:
#Html.DropDownListFor(m => m.Marks.StudentId, m.Drp_bind, "Select a Student")
The first argument is an expression describing the property on your model that you want to populate with the selected value from the drop down list in the post back. The second is the list comprising the values to which we need to data bind.
Note that your CSHTML will need more form fields within it bound to the other properties of the Marks property.
Your POST method would now take MarksViewModel as an argument and extract the Marks property from it to add to the DbContext for saving.
What's the best way to set default properties for new entities in DDD? Also, what's the best way to set default states for complex properties (eg. collections)?
My feeling is that default values should be in the models themselves as they are a form of business rule ("by default, we want X's to be Y & Z"), and the domain represents the business. With this approach, maybe a static "GetNew()" method on the model itself would work:
public class Person {
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public bool IsAlive { get; set; }
public List Limbs { get; set; }
public static Person GetNew() {
return new Person() {
IsAlive = true,
Limbs = new List() { RightArm, LeftArm, RightLeg, LeftLeg }
}
}
}
Unfortunately in our case, we need the collection property to be set to all members of another list, and as this model is decoupled from its Repository/DbContext it doesn't have any way of loading them all.
Crappy solution would be to pass as parameter :
public static Person GetNew(List<Limb> allLimbs) {
return new Person() {
IsAlive = true,
Limbs = allLimbs
}
}
Alternatively is there some better way of setting default values for simple & complex model properties?
This is an instance of the factory pattern in DDD. It can either be a dedicated class, such as PersonFactory, or a static method, as in your example. I prefer the static method because I see no need to create a whole new class.
As far as initializing the collection, the GetNew method with the collection as a parameter is something I would go with. It states an important constraint - to create a new person entity you need that collection. The collection instance would be provided by an application service hosting the specific use case where it is needed. More generally, default values could be stored in the database, in which case the application service would call out to a repository to obtain the required values.
Take a look at the Static Builder in Joshua Bloch's Effective Java (Second Edition). In there, you have a static builder class and you chain calls to set properties before construction so it solves the problem of either having a constructor that takes a ton of arguments or having to put setters on every property (in which case, you effectively have a Struct).