Transferring metadata from one EntityManager to another EntityManager - breeze

Currently I have a single WebAPI that returns the metadata for a number of client side apps. The client apps talk to different WebAPIs, not the one who provided the metadata. I don't like the idea of pre-generating the metadata, saving in a js file and reloading it at the client - the kind of approach RIA has.
How can I transfer the metadata from one EntityManager (connected to the webapi that provides the metadata) to "other" EntityManager which has the model entities so this "other" EntityManager can do the change tracking?

If you have an EntityManager, you can use its MetadataStore in the constructor for any other EntityManager like so:
var entityManager2 = new EntityManager({
serviceName: aServiceName,
metadataStore: entityManager1.metadataStore }
);

Related

ServiceBusTrigger in a Multitenant application - Dependency Injection for ServiceBusReceivedMessage

I have a multitenant application which uses scoped dependencies to retrieve a tenantId from an incoming httprequests to the Azure functions and instantiate various resources based on the tenant.
For example:
services.RegisterScoped((sp)=>
{
var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>();
var tenantId = httpContextAccessor.GetTenantId(); // extension method
// Instantiate some other tenant specific dependencies e.g. DBContext.
});
Now, I have a ServiceBusTrigger which processes messages for all tenants. The ServiceBusReceivedMessage parameter contains an object which has a tenantId property so that each message can be processes for a particular tenant.
Is there a way to have the ServiceBusReceivedMessage instantiate a resource, say a DbContext, from within the function? This is necessary because each message may have to persist some data via a DbContext, which needs to be instantiated with a specific connection string based on the tenantId in the message.
Some things I have considered:
Using Activator.CreateInstance(//pass in the tenant connection string after retrieving it manually)
Can ServiceBusRecievedMessage be registered within the serviceBusTrigger per message?? This seems hacky (there isn't a straightforward way to do that) but also the most preferred approach as the rest of the DI containers can be leveraged without having to instantiate objects manually as in the first option.
[FunctionName("MyCustomTrigger")]
public Task Run(
[ServiceBusTrigger("MultiTenantEndpoint")]
ServiceBusReceivedMessage message,
ServiceBusClient client,
ServiceBusMessageActions messageActions,
ILogger logger,
ExecutionContext executionContext)
{
var tenantId = message.GetTenantId();
// register tenantId as scoped for this request only somehow?
await injectedService.Process(message);
}
Alternate approaches or designs for this?

breeze-client - any way to consume metadata from Web API?

Hi I created a method on my Web API Controller that successfully returns the metadata as string. I am just wondering if there is a clever way of generating entities at runtime instead of generating entities in TS client side beforehand?
[HttpGet]
public string Metadata()
{
return this.dataContext.Metadata();
}
The point of generating the TypeScript entities beforehand is so that you have types and intellisense to help you write your code correctly.
But of course the EntityManager can create entities on the fly from the metadata; you just need to know the name of the EntityType:
let cust = manager.createEntity("Customer");
And you can query entities from the server without pre-generated classes:
const query = new EntityQuery('Customers').where('lastName', 'startsWith', 'C');
manager.executeQuery(query).then(qr => {
let customers = qr.results;
// do something with customers...
});
In the early days of Breeze, we always loaded the metadata from the server on-the-fly, usually as the app was starting up.
These days, I code in TypeScript, and I find it very helpful to have the metadata and classes pre-generated.
Figured it out. The above method is needed or at least one called Metadata of type HTTP GET. the data service in breeze-client needs to have the property hasServerMetadata to false and the magic happens.

Save new entity in changeRequestInterceptor method

Im just thinkin to save some audit details of all changes on entities to database.so im have come up with that "changeRequestInterceptor" which looks like where i can implement my audit logic in.
Well,the question is simply is it possible to add this newly created entity to request payload ?
var adapter = breeze.config.getAdapterInstance('dataService');
adapter.changeRequestInterceptor = function (saveContext, saveBundle) {
this.getRequest = function (request, entity, index) {
var em = saveContext.entityManager;
var en = em.createEntity('DbLog',
{
userId: //userId
logDate: new Date(),
log: //some log text
});
//How to add "en" entity to requet payload.
return request;
};
this.done = function (requests) {
};
};
I'm firmly with Jay in favor of creating audit records on the server, not the client. The client could care less and shouldn't bear the burden of creating the extra material nor have to burn bandwidth for that kind of stuff. It's really not a client concern.
There is a save interceptor in the Breeze-oriented server components. There is NO save interceptor in the Breeze client save pipeline.
We have such a thing in our DevForce product. After careful thought we did not bring it over to Breeze and we're confident that we were wise to leave it out. Interceptors add complexity and obscurity. Some times they are necessary (as with our server-side interceptors) but we don't think they are helpful or necessary for a client-side save operation ... for reasons I'm about to explain.
Breeze never calls EntityManager.saveChanges on its own. You do that. Which means you are in perfect position to decide what happens before Breeze does its thing. That includes creating supplementary entity changes just before save if that's what you need.
In our samples, we encapsulate the EntityManager in some kind of a service component (e.g., a "DataContext" or a "DataService"). Application layers (e.g., viewmodels) can't talk to an EntityManager directly; they have to go through the DataContext to perform persistence operation.
Your DataContext API should expose a "save" method (or methods) that wraps the EntityManager.saveChanges call with the appropriate business logic.
Follow this pattern and you'll find ample opportunities to implement pre- and post-save behaviors.
Of course Breeze does offer save interception at lower levels of the stack. The DataServiceAdapter, for example, handles the details of translating between Breeze entity representation and whatever your particular backend service requires in the way of HTTP setup and JSON objects. You want these details abstracted for you when writing your DataContext.
You might need some interception way down here ... and you'll find the requisite hooks. But now we're talking about what you can do below the Breeze entity abstraction. This feels like the wrong place to be adding/modifying/deleting entities even if it is technically possible to do so.
Another alternative is to perform the Add on the server instead of the client.
[HttpPost]
public SaveResult SaveWithFoo(JObject saveBundle) {
ContextProvider.BeforeSaveEntitiesDelegate = AddNewFoo;
return ContextProvider.SaveChanges(saveBundle);
}
private Dictionary<Type, List<EntityInfo>> AddNewFoo(Dictionary<Type, List<EntityInfo>> saveMap)
var foo = new Foo();
// update the entity with any custom data. For example:
foo.OrderDate = DateTime.Today;
var ei = ContextProvider.CreateEntityInfo(foo);
List<EntityInfo> fooInfos;
if (!saveMap.TryGetValue(typeof(Foo), out fooInfos)) {
fooInfos = new List<EntityInfo>();
saveMap.Add(typeof(Foo), fooInfos);
}
fooInfos.Add(ei);
return saveMap;
}

How can I design better communicate between application members and Web API and Signalr Hubs

I am working in a project which needs to communicate with users realtime. Basically I am following "synchronize pages over web api" path which is introducing in this video (also Brad Wilson has a nice video like this one) and the repository here for video.
My question is about mapping application members with their ConnectionIds which is producing by Signalr.
I used to be saving every signalr connection ID in a database table like:
ConnectionID
MemberID
ConnectionStatusID --> Connected(1), Disconnected(2), Reconnecting(3)
I was fetching member's connection IDs in most requests.
Then I decided to change this design. Now I am grouping every member with a unique string when OnConnected and OnDisconnected like this:
public override Task OnConnected()
{
Groups.Add(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
return base.OnConnected();
}
public override Task OnDisconnected()
{
Groups.Remove(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
return base.OnConnected();
}
Now I am not fetching anything from database about member connection IDs. It is only working over Web API for making synchronization between browser tabs.
I simply show how I am handling incoming Request and using Hub in Web API:
public HttpResponseMessage Example()
{
string msg = "Example to all";
//some other process
//Hub is an instance of a IHubContext
Hub.Clients.Group(string.Format("MyHub_{0}", HubUser.MemberID)).example(msg);
return Request.CreateResponse(HttpStatusCode.OK, msg);
}
So which one do you think is efficient way for using Signalr. What would you suggest is possibly better than these. Is making a dependency between hub and WebApi is a good design choice to go.
And also project will be deployed to multiple servers and Load Balancer will work in front of them (I am going to use Sql Backplane for this). There are few projects which must talk to Web API, indirectly to hub too.
I like your second solution as it should require less DB queries. It is no less efficient for SignalR to send to a group than it is for it to send to a connection id. You just need to ensure your group names (HubUser.MemberID) are unique and non-spoofable.
In SignalR 2.0, we make this pattern even easier: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider
If your users' MemberIDs match up with their IPrincipal.Identity.Name, then you can just change all your code to use Clients.User(HubUser.MemberID)....
If you don't want to base your SignalR user id on the request's IPrincipal, you can provide your own IUserIdProvider and inject it using SignalR's dependency resolver.
http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection

persisting MVC data to ORM

Java or dotNet world is rich of open source frameworks and libraries. We all like to use Spring and Hibernate almost everywhere.
Everyone agrees that hibernate is a very handy tool.
What Hibernate can do ? well, Basically - Hibernate can track our domain objects changes and persist only modified data to database, that is it.
Basically, That is everything we want. I want to load some records from database, do some modifications to them, and call transaction.commit(), and all modifications get persisted, instantaneously.
That is excelent, right !
But how about web world ? In web applications database session must be closed.
I cannot load some domain objects and wait for user to do modifications through HTTP, and persist those objects after modifications.
We have to use detached objects or DTO. How it works ?
User makes modifications in HTML browser, spring Mvc automatically thransfers those HTML modifiactions to our customized DTO objects using MVC model binding,
then we do some programming effort to transfer modifications from DTO objects to hibernate domain objects and only then we persist them.
For example - we have a web form that updates Customer address, and another form which updates customer details.
We must have two different business layer methods - UpdateAddress() and UpdateDetails(), both methods must accept some kind of DTO,
one represents address information, the other represents details infprmation.
We also have custom logic that transfers data from those 2 DTO to the domain class 'Customer'.
Yes, of course, instead of DTO objects we could reuse our domain classes. But it does not make it simpler.
In both cases we will still have to implement custom logic that transfer modifications to persistent objects,
I cannot persist detached object rightaway, because usually domain classes have lots and lots of properties representing numerous relations, for ex. Customer has - Orders property. When I update customer address I don't want to update its orders.
Is there a beautifull universal way to mapping modifications from mvc model to domain objects without writing a lot of custom code and without risk of overwriting too many fields ?
It's good practice to have a data access layer, which translates into having a repository for each domain object / entity. Furthermore, all repositories share common code so you you naturally have an abstract repository:
public abstract class AbstractRepository<E extends BaseModel> implements Repository<E> {
#PersistenceContext
private EntityManager entityManager;
private Class<E> entityClass;
public AbstractRepository(Class<E> entityClass) {
this.entityClass = entityClass;
}
protected EntityManager getEM() {
return entityManager;
}
protected TypedQuery<E> createQuery(String jpql) {
return createQuery(jpql, entityClass);
}
protected <T> TypedQuery<T> createQuery(String jpql, Class<T> typeClass) {
return getEM().createQuery(jpql, typeClass);
}
#Override
public E merge(E entity) {
return getEM().merge(entity);
}
#Override
public void remove(E entity) {
getEM().remove(entity);
}
#Override
public E findById(long id) {
return getEM().find(entityClass, id);
}
}
It's also good practice to have a service layer where you are to create, update and delete instances of an entity (where you could pass through a DTO to the create and update methods if you so desire).
...
#Inject
private CustomerRepository customerRepository;
public Customer createCustomer(CustomerDto customerDto) {
Customer customer = new Customer();
customer.setEmail(customerDto.getEmail());
...
return customerRepository.merge(customer);
}
public Customer updateCustomerAddress(Customer customer, String address) {
customer.setAddress(address);
return customerRepository.merge(customer);
}
...
So it's up to you how many update methods you want. I would typically group them into common operations such as updating the customer's address, where you would pass the customer Id and the updated address from the front end (probably via ajax) to your controller listening on a specific endpoint. This endpoint is where you would use the repository to find the entity first by Id and then pass it to your service to do the address update for example.
Lastly you need to ensure that the data actually gets persisted, so in Spring you can add the #Transactional annotation either to you Spring MVC controller or to your service that does the persisting. I'm not aware of any best practices around this but I prefer adding it to my controllers so that you're always guaranteed to have a transaction no matter what service you are in.

Resources