DynamoDB and .NET Object Persistence Model, using 'ADD' values instead of overwrite - c#

I have several DynamoDB tables that will act as aggregate data stores (we are 'rolling up' reports on the fly). I was hoping to use the .NET: Object Persistence Model (where you build classes that have annotations on them). The problem is the DynamoDBContext object only seems to have a 'Save' method and not a 'Save and Add values' method. Because the time between retrieving an object from Dynamo and the time to write to that row again could be larger than a trivial amount, and more than one thread could be attempting to increment, I don't want the increment to be done in the .NET code. Instead I want the .ADD AttributeAction. But I'm not sure if you can specify an attribute action with the Object Persistence Model. Does anyone know if that's possible?
[DynamoDBTable("my_table")]
public class MyRecord
{
[DynamoDBHashKey(AttributeName = "my_id")]
public string MyID{ get; set; }
/// <summary>
/// Hash of the Region and Country fields for unique data lookup from DynamoDB
/// </summary>
[DynamoDBRangeKey(AttributeName = "location")]
public string Location { get; set; }
[DynamoDBProperty("my_count")]
public int MyCount{ get; set; }
Above is a sample object. The idea is that MyID gets several 'counts' which represent user actions. I don't want to have to get mycount then add 1 in .NET then re-push. I'd rather run the 'Add' command and always send '1' to mycount and have dynamo do the math to guarantee correctness.

Since I'm not finding a ton of resources on this, I've decided to write my own extension method for this. It's not perfect in that you can't divine the DBClient object from the context because it's not public, so you have to pass it in.
https://gist.github.com/edgiardina/9815520
However, I'll leave this question unanswered since I don't know if there's an easier way to execute this.

Related

Assign Different Type to Class Property

I have created a class to store data from API calls I am making. It returns JSON with some meta information, and then an array of data depending on the call being made. The meta information will always have the same fields, so I have created a "Root" class for this, but the data will be different depending on the call being made, so I have created different classes for each type of data, e.g. user data, company data, etc. As shown below, I currently have the "data" property set to a list of objects, but I am trying to figure out the best way to incorporate the different types of data that can be returned, since it will vary based on the call being made.
Right now I have the data saved as a list of objects, but I would like this to change depending on what data I am receiving. Like, if I am retrieving users, I would like for it to be a list of users.
What is the ideal way to accommodate for this? The only way I can think to do it now is to create a different "Root" class for every type of data I am expecting to receive, but that doesn't feel like it should be the most concise way to do it. I was looking into making this a factory design pattern but I wasn't sure that it fit this scenario.
Just use a generic base class:
public abstract class ApiCallResult<T>
{
// With your properties
// public int Limit { get; set; }
// [...]
//
public IEnumerable<T> Data { get; set; }
}
Then define a result per api call.
public class UserApiCallResult : ApiCallResult<User>
{
}
Created a small working example here:
dotnet fiddle

Distinct event types on same collection - MongoDB and .NET Core

I want to use MongoDB to store domain events in a system written with .NET Core and C#.
I've googled a little about this, and it seems it is a common practice to have a single collection called events and simply store all events there. I've also seem people to create one field type to distinguish events. An example of this is Slide 66 of this presentation.
So if I wanted to save one UserCreated event I would add it with type user-created, and so forth.
Now I'm in doubt with respect to the mapping when it comes to using .NET Core.
Two distinct events will in general have different schema, so I think that the automatic mapping would do no good. Of course I could use the option of ignoring extra elements. But it may be the case that two events have subsets of properties which are equal, for example, all of them will have a OccurredOn DateTime. I think this could be an issue.
My idea was to query the field type. Something like:
colection.Find(BsonDocument.Parse("{type: user-created}"))
But I don't know if that is the best option, or if there is a way to set up a mapping so that the MongoDrive knows that whenever we try to get an instance of UserCreated it should look just for that type, and when we try to insert, it should create the correct type field.
In that case: given that we save distinct event types to the same collection, what is the correct approach to map this into the right C# event objects?
You could use a container like this one.
public class DomainEventContainer
{
public ObjectId Id { get; set; }
public string Type { get; set; }
public string EventData { get; set; }
}
And then based on the value of DomainEventContainer.Type, you could deserialize EventData into your desired type.

How should aggregate expose info from child entity?

[ Follow up from this question Should entity have methods and if so how to prevent them from being called outside aggregate ]
I am trying to understand in full details how aggregate root exposes data from its child entities to outer world; in particular, at least repository will need that info in order to be able to save it.
So, for the sake of the argument, lets consider these rules:
Person have a few channels of communication: phone, email, facebook account (might as well be a collection of each of those but for simplicity lets say its just one of each).
Person can choose to make any of those channels public so that other Persons can contact him or make any of those private so that he can't be pinged through that particular channel.
Person can choose global setting of not being contacted at all. In that case, its forbidden to switch any of the phone, email, facebook to public.
[ Note: the model i'll show now might not be the best one but lets leave remodeling aside for now and focus on exposing child entity infos ]
lets say we have aggregate root Person (c# code), only with example for Phone entity as others are the same logic:
class Person {
...
private Phone Phone { get; set;}
public bool WantsToBeContactedAtAll { get; }
public void ExposePhoneNumberPublic() {
if(!this.WantsToBeContactedAtAll)
throw new SomeError("Not allowed.");
this.Phone.PublishPhoneNumber(true);
}
public void HidePhoneNumber() {
this.Phone.PublishPhoneNumber(false)
}
}
class Phone {
//this is identifier
public readonly string PhoneNumber { get; private set; }
public string Description { get; private set; }
public boolean ShouldBePublished { get; private set; }
public Phone(string phoneNumber, string description, bool shouldBePublished) {
//set values
}
public void PublishPhoneNumber(bool preference){
this.ShouldBePublished = preference;
}
So, what we want to prevent is someone doing:
Person Adam = new Person(...);
Adam.Phone.PublishPhoneNumber(true);
But now, we still need info from Adam.Phone if for nothing else, then for the repository to access it when saving aggregate:
_personRepository.Add(Adam);
Questions:
How to expose Person.Phone info?
Should we expose some copy of the Phone property as a struct (value object)?
Have Phone as private type within Person aggregate and expose another PhoneReadOnly type what would be just a class with properties and getters.
Another way of asking those all question is: how can at least repository read Person.Phone information that it needs in order to be able to save Person?
Please treat me as a complete idiot and explain in details.
Thanks
How shoud aggregate expose info from child entity?
In a way that doesn't allow the caller to change the state of the aggregate.
Pass a primitive value
Pass a reference to an immutable object
Pass a copy of an object
Copies of information are fine, because you can't change my state by changing your copy of my data. References to immutable objects are fine, because you can't change them at all, therefore you can't change my state. But giving you a reference to my mutable state increases the odds of a programmer error.
Let's consider the repository example for a moment -- repositories, remember, are used to give the application the illusion that all of the aggregates are just members of some vast, in memory collection. To support this illusion, the repository needs two functions -- one that takes a representation from our stable data store and creates from it the domain model entities that make up the aggregate, and another that takes the aggregate and constructs from it the representation to put in the data store.
Let's pretend that we had some really naive aggregate that was just an array of integers
class Aggregate {
int [] State;
}
And then we imagine the functions that a repository might need to load and store this aggregate
Aggregate a = Aggregate.from(state)
int [] state = a.state
Now, what happens if we try to cheat?
int [] state = a.state;
state[0] = 12345;
Did a change? Since we want the domain model to be the authority for the state of the world, the answer had better be "no". Which in turn means that the aggregate doesn't yield a reference to its own array, but instead a copy of that array.
The same principle applies if we think about an aggregate with an array of child entities.
class Aggregate {
Child [] children;
}
So what does this aggregate yield? Not it's own array, because that would allow the client to change the aggregate by replacing a Child. But it can't just copy the array either, because we could call methods on one of the child array elements to change itself, which would indirectly change the state of the aggregate.
So we don't return an array of children, we return an array of descriptions of children. It's a sort of "deep copy". The descriptions contain copies of data, but no references -- nothing that links back to the internals of the entity itself -- and so it is safe to yield the description to a caller, who can do what they like with it (including sticking the description into a document store for later recovery).
I tend to think that making your child entities (immutable) value objects simplifies this issue a lot.
A rule of thumb is that you never modify a value object, you replace it. Unlike controlling what people do with the inside of your sub-entities, assigning a value to a direct property of the AR is something you can easily restrict from the root. You can just mark the setter as private and only allow changing it by going through the adequate AR method:
class Person {
public Phone Phone { get; private set; }
public void ExposePhoneNumberPublic() {
if(!this.WantsToBeContactedAtAll)
throw new SomeError("Not allowed.");
Phone = new Phone(Phone.Number, Phone.Description, shouldBePublished: true);
}
}
Note that the part where you take the existing Phone and new up a slightly different one could be done more elegantly - see the "with" keyword here.
Another way of asking those all question is: how can at least
repository read Person.Phone information that it needs in order to be
able to save Person?
I believe that's actually a totally different question. Usually, reading is not the hardest part - if you want any client code to be able to read the Phone, there's no reason that a Repository won't. Writing can be more tricky, as a well-encapsulated aggregate root doesn't necessarily let you change it like that. With ORMs, making the setters protected will work most of the time. An alternative is to use internal with InternalsVisibleTo the concrete repository's assembly, or work with a fully mutable backing state object.

C# Sort object with listcollection member

I have an MVC web app where users upload a text file and I parse it out.
The requirement just changed and they will be uploading multiple files of the same kind now. I parse a single file by sending a file-path to the method below, ReadParts which opens a stream and calls the method parseReplicateBlock to retrieve desired fields. For multiple files I could read all the files into one big stream but I am afraid it could exceed the buffer limit etc.
So I am thinking to parse file by file and populate results into an object. My requirement then, is to sort the records based on a date field.
I just need some help in how to write this method ReadLogFile in a better way, espceially for sorting based on initialtionDate and initiationTime. I want to find the minimum record based on initiationDate and Time and then do some other logic.
The problem is if I sort the list member within the object, I would loose positiong of the other records.
You appear to be storing each field of the record in a separate collection within LogFile. This seems a very strange way to store your data.
If you sort one of these collections, then of course it will bear no relationship to the other fields any longer since they are unrelated. There are huge areas for bugs too if you are relying on all the collections tallying up (eg if a field is missing from one of the parsed records)
Instead you should be have a class that represents a SINGLE record, and then Logfile has a SINGLE collection of these records. eg:
public class ReplicateBlock
{
public string ReplicateId { get; set; }
public string AssayNumber { get; set; }
public DateTime InitiationDate { get; set; }
//etc
}
public class LogFile
{
public List<ReplicateBlock> ReplicateBlocks = new List<ReplicateBlock>();
}
I have to say that your code is very difficult to follow. The fact that all your functions are static makes me think that you're not particularly familiar with object oriented programming. I would suggest getting a good book on the subject.

Design Decision: Generate OrderNumber which depends on a database value

I'm building an ordering system using C# and got a problem on order number generation.
I have an Order class which have an OrderNumber property. I want to make the OrderNumber property readonly, because it's not safe to change OrderNumber.
Because the ordering steps are very complex (4 steps, some steps might take 10 minutes to complete), so I need to save the order in each step. But the client don't want to waste OrderNumber (order numbers are in "Year-Month-An_DB_Value" format), beause the last part of the OrderNumber indicates the order count in that month. So the OrderNumber should be assigned only when the user click "Request Verification" button.
For generating OrderNumber and keep Order class clean(have no dependency to database and can be unit tested), I want to make IOrderNumberGenerator interface as an argument of the constructor of Order class, like this:
public class Order {
public string OrderNumber { get; private set; }
public Order(IOrderNumberGenerator generator) {
// ...
}
}
But there's a problem:
Order can be first saved without having OrderNumber assigned. So if some days later, the user want to pass an Order to the order verifier, he will click the "Request Verification" button, and the system will retrieve the Order object from database via O/R Mapper (I use NHibernate), note that here we have no way to pass the IOrderNumberGenerator, because the Order object is retrieve from O/R Mapper, the ORM will reconstitute the Order object by calling the default constructor of the Order class (so we have no way to pass IOrderNumberGenerator). Here is the demo code:
Order order = repository.GetOrder(orderId);
// code to generate the order number
xxx.SubmitChanges();
So my question is, how to resolve the order number generation problem while still keep the Order class clean and easy to do unit testing.
Updates:
I'm now thinking the create a method named GenerateOrderNumber() in order class, and pass the IOrderNumberGenerator, like this:
public class Order {
public void GenerateOrderNumber(IOrderNumberGenerator generator) {
_orderNumber = generate.Generate();
}
}
I think it can resolve the problem, but any better solutions?
BTW: this is an extended question from my last question: Design Decision: OrderNumber property in Order class - Public or Private?
Thanks!
Considering that you want to generate OrderNumber from code, and considering your note:
"So the OrderNumber should be assigned only when the user click "Request Verification" button"
I would say Generate order on "Request Verification" click using OrderNumberGenerator.
Something like this:
public class OrderNumberGenerator : IOrderNumberGenerator
{
public OrderNumberGenerator(Order order)
{
//generate new order number for order parameter
}
}
In other words, generate an order at the moment of request (only if necessary), and inverse dipendency of types Order<->IOrderNumberGenerator
EDIT
By the way consider also generation of OrderNumber on DB level, if it's possible obviuosly in your case, like Yahia suggested, most reliable solution.
Hope this helps.

Categories