I am developing a real time multiplayer game using SignalR. The message delivery logic is not very simple which I could not handle it by using Groups.
For example, one message will be delivered to users with some custom property equals to some dynamic value. It means the target audiance can not be handled by
Clients.All
Clients.AllExcept
I have a mapping class something like this:
public class Player
{
public dynamic Client { get; set; }
public string ConnectionId { get; set; }
public string Name { get; set; }
}
Somehow I do detect all my audiences in a List object.
What is the best way to send message to everyone in the list? Enumerating through list and calling
foreach (var loopPlayer in players)
{
player.Client.sendMessage(message);
}
Or
List<string> ids = new List<string>();
foreach (var loopPlayer in players)
{
ids.Add(item.ConnectionId.ToString());
}
Clients.Clients(ids).sendMessage(message);
My concern about the first one is, it will serialize the message every time. About the second one, I don't know how it is working behind the scene.
The both approach is working but I am concerning about performance and trying to find the best practice. Or which any other approach I might use?
As you said, enumerating over list of clients serialize message each and every time (and store those serialized messages in internal buffers etc etc). If message is same, this is unnecessary CPU\memory overhead.
Clients.Clients(ids) serializes message only once so performance vise, its definitely way to go.
The message delivery logic is not very simple which I could not handle it by using Groups. For example, one message will be delivered to users with some custom property equals to some dynamic value.
Groups work in scaleout scenario out of the box which is huge benefit if you ever find yourself in need to scaleout. So maybe try to find some way to simplify "group assigment logic" even at cost of delivering some messages to more clients and doing "filtering" client side...
Related
I am building an app that integrates Plaid API to access user bank info (logins, accounts, transactions, etc.). I'm trying to follow DDD principles.
Here is a general idea of how the Plaid API flow works:
A user provides his email/password for some bank institution. If valid, a plaid Item is created. This object associates a user to a set of bank credentials and contains an access token which can be used to further interact with the API.
Every plaid Item has access to a certain set of bank Accounts.
Every bank Account has a set of Transactions
So far, I created 3 entities in my domain layer: Item, Account and Transaction. I created a repository with basic CRUD operations for each.
public class Item
{
public string Id { get; set; }
public string AccessToken { get; set; }
public string UserId { get; set; }
...
}
public class Account
{
public string Id { get; set; }
public string ItemId { get; set;
...
}
public class Transaction
{
public string Id { get; set; }
public string AccountId { get; set;
...
}
As you can see, the relationship between these entities is:
User HAS Item -> Item HAS Accounts -> Account HAS Transactions
My question is, what happens when I need to find an entity by an indirect parent? For example: GetTransactionsByItemId or GetAccountsByUserId. Based on DDD, where should this logic go?
Because of how my data is structured (No-SQL chain of 1-many relations) I know I have to do these sort of queries in multiple steps. However, I've read that a Repository should only be concerned about it's own entity so I suspect that injecting the ItemsRepository and AccountsRepository to the TransactionsRepository to add a GetTransactionsByItemId method might not be a good idea.
I also read about injecting many repositories to a Service and managing all these "joins" from inside. However, I can't come up with a name for this Service, so I'm worried that's because conceptually this doesn't make much sense.
I also read about Aggregates but I'm not sure if I recognize a root in these entities.
Another option I can think of is to try shortening relationships by adding an ItemId to every transaction for example. However, this would need to be a hack because of how I get the data from the api.
I would say your aggregation root would be an Item. If I got the structure right, Accounts cannot exist withoug Items and Transactions without account. So you could be ok just with ItemsRepository:
public class ItemsRepository
{
public async Task<Item> GetById(long id, IncludesSpec includes)
{
return await this.context.Items
.Where(c => c.Id == id)
.Include(c => c.Accounts).ThenInclude(c => c.Transactions)
.SingleOrDefaultAsync();
}
}
Than you get an Item with all the loaded data in it. The IncludesSpec is up to you: it would contain which includes should be made and includes shall be added dynamically in the repository method.
As of .net ef core 5 you can do filtered Includes, like .Include(c => c.Accounts.Where(...)), so you could further narrow the actual include down based on your requirements. You could pass another parameter which would contain this filter information.
Also your Item should expose Accounts as read-only collection (use backing field for EF) and provide a method AddAccount() so that nobody can modify your DDD item as pure entity.
What would make the most sense, I believe, would be to have a Service with multiple Repositories injected into it.
You could have one ItemRepository which returns Item objects, one AccountRepository which returns Accounts, one TransactionRepository returning Transactions and one UserRepository returning Users.
If your data model makes it cumbersome to do your query in one request, then have a function in your service which is transactional (ACID : either it all completes or it's all rollbacked) which does different queries to the each injected repository, then builds the objects and returns them.
If you do see a way to make it one query, you can hard-code that query inside the relevant repository. From Domain-Driven Design, Evans:
Hard-coded queries can be built on top of any infrastructure and without a lot of investment, because they do just what some client would have to do anyway.
On projects with a lot of querying, a REPOSITORY framework can be built that allows more flexible queries.[...]
One particularly apt approach to generalizing REPOSITORIES through a framework is to use SPECIFICATION-based queries. A SPECIFICATION allows a client to describe (that is, specify) what is wants without concern for how it will be obtained. In the process, an object that can actually carry out the selection is created.[...]
Even a REPOSITORY design with flexible queries should allow for the addition of specialized hard-coded queries. They might be convenience methods that encapsulate an often-used query or a query that doesn't return the objects themselves, such as a mathematical summary of selected objects. Frameworks that don't allow for such contingencies tend to distort the domain design or get bypassed by developers.
I am writing an API for my ASP.NET application that other developers will use. The API will basically return a list of people with their first name, last name, and id. There are lots of ways to write web services in ASP.NET, the easiest probably being create a web service function (asmx) that returns a DataTable. This is simple enough for other .NET developers to deal with, but I am not convinced that this is the best way to write a web service for general platform and language independence.
What is the currently accepted standard to write a web service like this that plays well in the wild today?
Some ideas that come to mind from experience:
Use WCF, not .asmx. WCF does all the same things that ASMX files do, and is generally the replacement for ASMX services (see here and here).
Write methods using simple POCO data types, like List<Person> rather than DataTable. Basic types serialize more easily and will make more sense in other programming environments since you want your service to be language independent.
Provide generic CRUD methods for managing data. Depending on how your service will be consumed, if the user needs to modify data, a simple method is to provide getBlah(), updateBlah(obj newObj), deleteBlah(obj objToDelete), etc. that use the same data types.
Hide the details that the service consumer doesn't need to know, rather than just blindly exposing all of your data types, structures, and field names as-is. This will make your service more robust for handling internal changes, and you can simplify and control what the end-users see. For instance, if you have a Person class with 30 properties, and only 5 are relevant to the end-user, provide a class that interfaces between Person and a PersonSimple class which is exposed. Without this layer, your end-users will have to modify your code every time you change your data structure, and you will be locked down by this tight coupling.
If security is important
Execute your service over SSL. This protects data transfered over the wire from being sniffed.
Use authentication, either with a Login method and session, or SOAP headers. Services by default are anonymous unless there is some sort of authentication scheme. Even if you think nobody will find your service because you only provide the URL to your users, it will get out somehow, somewhere, and people will try to misuse the service when it does. Plus, you can control who can do what by different logins and authorization schemes.
I am currently working on a similar issue: A web api service in .NET that receives data tables as input parameters, apply some operations on them (using Table Valued Functions), and return some output data tables.
In your case, you don't need to use a complex class like DataTable; you could use an array (List<>) of a simple class with fields like first name, last name and id. Using Web Api of ASP.NET you could do something like the following:
1) Create a new WebApi project in Visual Studio: For example (in VS 2012) C# > Web > ASP.NET MVC 4 Web Application > select "Wep Api" as project template
You will see a VS project with lots of folders, including one named Models
For help see: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
2) Create a new model code file Person.cs with a class like the following:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string[] Friends { get; set; }
}
3) Create e new controller code file PersonController.cs with methods for getting, inserting and updating records of the database. All the necessary serialization/deserialization (JSON and XML) and data binding is done automatically by the Web Api environment set by the project template.
// Get all the records of persons
public IList<Person> Get()
{
// read database into a list of persons (List<Person>)
// return List<Person>
}
Return record of a selected person:
public Person Get(int id)
{
// read database for a selected person
}
Parameter binding (reading a JSON/XML content sent by http POST into an object, or into a list objects) is also done automatically, as easy as the following:
// parameter binding: Create a Person object with content from XML/JSON
public void ReadPerson(Person p)
{
Trace.WriteLine(Person.Id);
}
public void ReadPersonList(List<Person> plist)
{
Trace.WriteLine(plist.Count);
}
I may have the wrong "pattern" here, but I think it's a fair topic.
I have an ASP.Net MVC application in which it calls out to a WCF service to get back the ViewModels that will be rendered. (the reason it's using a WCF service is so that other small MVC apps may also call on for these ViewModels...only internally, it's not a publicly available thing so I can change anything either side of the service. The idea is to move the logic that was in the website, closer to the server/database so the roundtrips aren't so costly - and only do one roundtrip overall from the webserver to the database server).
I'm trying to work out the best thing to return these "ViewModels" in from the service. There are lots of common little bits of functionality, but each page may want to display different subsets of these things (so homepage maybe a list of tables, next page, a list of tables and users that are available).
So what's the best way of returning the information that the page wants, hopefully without the webservice knowing about the page?
Edit:
It's been suggested below that I move the logic in process. This would be a lot faster, except that's what we're moving away from because it is actually a lot slower (in this case). The reason for this is that the database is on one server, and the webapp is on another server, and the webapp is particularly chatty at points (there are pages it could end up doing 2K round trips - (I have no control over reducing this number before that's suggested)), so moving the logic closer to the db is the next best way of making it more performant.
I would look at creating a ViewModel per each MVC app/view. The service could just return the maximum amount of data for the "view" in a logical sense and each MVC app uses the information it wants when composing the ViewModel for it's view.
Your service is then only responsible for one thing, returning data specific to a view's function. The controller of each app is responsible for using/not using pieces of the returned data.
This will be more flexible as your ViewModels may require different validation rules as well. ViewModels also have MVC-specific needs(SelectList etc..) that shouldn't really be returned by a service layer. It seems like something can be shared at a glance, but there are generally lots of small differences that make sharing ViewModels a bad idea.
class MyServiceViewResult
{
public int SomethingEveryViewNeeds { get; set; }
public bool OnlyOneViewMightNeedThis { get; set; }
}
class ViewModel1
{
public int IdProperty { get; set; }
public ViewModel1(MyServiceViewResult result)
{
IdProperty = result.SomethingEveryViewNeeds;
}
}
class ViewModel2
{
public int IdProperty { get; set; }
public bool IsAllowed { get; set; }
public ViewModel2(MyServiceViewResult result)
{
IdProperty = result.SomethingEveryViewNeeds;
IsAllowed = result.OnlyOneViewMightNeedThis;
}
}
Instead of having a web service, why don't you just implement the service as a reusable library that encapsulates the desired functionality?
This will also allow you to use polymorphism to implement customizations. WCF doesn't support polymorphism in a flexible way...
Using an in-proc service will also be a lot faster.
See this related question for outlines of a polymorphic solution: Is this a typical use case for IOC?
Is it acceptable to cache an instance of the database connection on application start?
Looking at the MSDN documentation on thread safety, I quote:
Any public static [...] members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Given that, is it acceptable/safe for code such as this example below:
public static class BookingMapper
{
public static Database Db { get; set; }
static BookingMapper()
{
Db = DatabaseFactory.CreateDatabase();
}
public static string GetBooking(int id)
{
using (DbCommand cmd = Db.GetStoredProcCommand("getBooking"))
{
Db.AddInParameter(cmd, "#Id", DbType.Int32, id);
using (IDataReader dr = Db.ExecuteReader(cmd))
{
...
}
}
}
}
If it is acceptable, what are the benefits/drawbacks of using such an approach over simply instantiating the Database on every single method call?
Thanks in advance.
Update:
Further research has pointed me to a PrimaryObjects.com article which, in the Putting the Database Factory to Use section suggests that this is acceptable. But I'm still wondering if there are pros/cons to doing it this way?
Similar question
1) There are two ways to interpret that standard phrase on Thread Safety from MSDN, and I wish they'd clarify it. Your interpretation would be nice, but I believe that what it means is that:
Any members (methods, fields, properties, etc) that are part of this type, and that are public and static, are thread safe
(e.g. there are two ways to interpret the subphrase "members of this type")
2) Generally, you don't want to share a db connection around - you want to open a connection, do your job, and close it. You can't generally have multiple open readers associated with a single connection (this is generic db/connection advice, not ent library specific).
3) On some further reading inside the ent library, the Database object returned by the CreateDatabase call isn't a connection itself, and it looks like the connection management is handled as I stated in point 2. So it looks like the Database object itself can be safely shared around.
So let's say we have a domain object such as the following
public class Person
{
public string Name { get; set; }
public IList<PhoneNumber> PhoneNumbers {get; set; }
public IList<Address> Addresses { get; set; }
}
The Person is not valid until a name, phone numbers, and addresses have been entered. How do you guys handle this using ASP.NET MVC and forms...
I was thinking you could serialze the Person to session and have multiple views for editing Name, adding phone numbers, adding addresses - the controller actions would modify the person in the session and a final Save action would push to database.
I don't really like having multiple views and using the session. Another option would be to have a single very complex form that could have "dynamic" sections of elements for adding/removing phone numbers, addresses within the browser prior to posting to the save action.
What is everyone doing with complex objects and editing via forms?
Thanks!
I would usually use the "dynamic section" route.
However, I would not make your validation so strict that the user is unable to save work in progress. A list of phone numbers, addresses, etc., can take quite a while to enter. It is beneficial to the end-user to be able to save their work from time to time in case they lose Internet connectivity or something. It's probably a good idea to save the records automatically via AJAX from time to time if your data entry form is quite large. (Like Gmail.) Therefore, your model should allow them to save incomplete work from time to time, and run the whole validation only when they say they are "done."