JDOQL to embed objects from different databases - jdo

I have a data object, AssetDO, in the database table FOO.DBO.ASSET. Asset has a column for userId, which refers to a table in a different database, BAR.DBO.USER.
Is it possible to write a JDOQL query that supports UserDO (the user objecT) being referenced from the AssetDO class, rather than just including an id and me doing the lookup later?
I want:
public class AssetDO {
private User user;
public User getUser() { .. }
public void setUser(User user) { .. }
}
instead of:
public class AssetDO {
private long userId;
public long getUserId() { .. }
public void setUserId(long userId) { .. }
}

JDOQL allows reference to any field that has its persistence defined in the current PMF. JDO allows catalog and schema to be specified for any class, so consequently you can select across catalogs/schemas just like you can in an RDBMS (as long as the two databases are in the same server)

Related

Ardalis CleanArchitecture - BaseEntity & Composite Keys for AggregateRoots

What is the recommendation for extending BaseEntity as an AggregateRoot is I need to have a composite Key?
Essentially I need to be able to manage an Entity that would normally be configured in EFCore like:
builder.HasKey(z => new { z.PartA, z.PartB });
Currently the template gives us the following definition of BaseEntity, but it's unclear to me how I might need to setup the EntityTypeCuilder config, and how the Aggregates might handle this scenario under the hood.
// This can be modified to BaseEntity<TId> to support multiple key types (e.g. Guid)
public abstract class BaseEntity
{
public int Id { get; set; }
public List<BaseDomainEvent> Events = new List<BaseDomainEvent>();
}
Paul

Auto populate timestamp in DynamoDB

I come from Relational Database background and we have a way to populate timestamp for row creation and update.
I am having difficulty finding similar feature for DynamoDB.
I checked DynamoDB to check if they support autopopulate the date timestamp for every entry in dynamoDB. I see it is possible to create random ID but that is not what I need.
My usecase is to add a timestamp entry automatically when I add any entry to DynamoDB Table. Appreciate any pointers. Thanks
Java Solution using Annotation (Data modelling package)
You can use the DynamoDBAutoGeneratedTimestamp annotation.
#DynamoDBAutoGeneratedTimestamp(strategy=DynamoDBAutoGenerateStrategy.CREATE)
public Date getCreatedDate() { return createdDate; }
public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; }
#DynamoDBAutoGeneratedTimestamp(strategy=DynamoDBAutoGenerateStrategy.ALWAYS)
public Date getLastUpdatedDate() { return lastUpdatedDate; }
public void setLastUpdatedDate(Date lastUpdatedDate) { this.lastUpdatedDate = lastUpdatedDate; }
DynamoDBAutoGeneratedTimestamp
There is no such functionality like
DEFAULT CURRENT TIMESTAMP or UPDATE CURRENT_TIMESTAMP.
You will have to set the date by yourself.
However if you want to keep track of changes on updates then you can use something like atomic counters.
Thus on every update your will increment the counter value.
What worked for me, using aws-sdk-version 2.17.169:
First, you need to define the extension to support
AutoGeneratedTimestampRecordExtension.
#Bean
public DynamoDbEnhancedClient dynamoDbEnhancedClient(){
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient())
.extensions(AutoGeneratedTimestampRecordExtension.create())
.build();
}
Then, create a converter for java.time.Instant. As this is the only one supported at the time.
import java.time.Instant;
public class InstantToStringTypeConverter implements DynamoDBTypeConverter<String, Instant> {
#Override
public String convert(Instant instant) {
return instant.toString();
}
#Override
public Instant unconvert(String s) {
return Instant.parse(s);
}
Finally, on your model, add the annotations:
#DynamoDbAutoGeneratedTimestampAttribute
#DynamoDBTypeConverted(converter = InstantToStringTypeConverter.class)
public Instant getCreated() {
return created;
}
public void setCreated(Instant created) {
this.created = created;
}
#DynamoDbAutoGeneratedTimestampAttribute
#DynamoDBTypeConverted(converter = InstantToStringTypeConverter.class)
public Instant getUpdated() {
return updated;
}
public void setUpdated(Instant updated) {
this.updated = updated;
}
See some reference here

How to organize a project into three tiers?

I have an asp.net website and I would like to organize it into three layers
DataAccess
Domain
UI
What specifically goes in each of these layers?
e.g
Data
- Models
- Repositories? Would that be just interfaces
- IoC?
Domain
- Services?
UI
- javascript
- Area specific models?
- css
Could someone provide a simple guideline for organizing an asp.net website like this?
As other people have said each situation is different, but for a basic architecture, I would probably go along with something like this. It has gotten me out of a few jams and up and running quite quickly.
Infrastructure Layer
This is where all the data access is done. Database connection management, etc.
The Repositories include all queries to the database.
The Dependency Resolution sits here too. Use your DI Container of choice.
Domain Layer
This is where all you business logic sits.
The Domain Services Interfaces are what the UI layer call to use your business logic
UI
Pretty obvious this one....
Code Example
--UI
public class MyController
{
private readonly IMySerivce _myService;
public MyController(IMySerivce myService)
{
_mySerivce = myService;
}
public void MyAction()
{
_myService.DoSomeAction();
}
}
--Domain
public Interface IMyService()
{
void DoSomeAction();
}
public class MySerivce : IMyService()
{
private readonly IMyRepository _myRespository;
public MySerivce(IMyRepository myRepository)
{
_myRepository = myRepository;
}
public void DoSomeAction()
{
_myRepository.Save();
}
}
public interface IMyRepository
{
void Save();
}
--DataLayer
public MyRepository : IMyRepository
{
public void Save()
{
//Manage Save here
}
}
Additionally I usually have a separate area for unit/integration tests.
Update
This most definitely is dependent on your situation. It is very hard to say what method is best without fully understanding what you are ultimately trying to build.
From the list below you can see which method works well for you or fits well with your architecture.
Regardless of which one you choose, your Repository Implementation will have to have a dependency on your Domain Objects project.
Some techniques in doing it include:
No Mapping
Your Domain Objects really then become dummy mappings to your tables. i.e. have a table in your database call User. Then have a Domain Object called User. This is by far the simplest technique.
--Domain
public class User
{
public int Id {get; set;}
public string UserName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string Password {get; set;}
}
--Infrastructure
public class UserRepository : IUserRepository
{
public Core.User GetById(int id)
{
return DBConnection.GetByIdQuery(id);
}
}
Mapping
Martin Fowler describes it here
It is possible in your infrastructure layer to have what are known as Domain Transfer Objects (DTO) that represent your database tables. Similar to above, a table called User, a DTO called User. Both having the same properties.
Your domain Entity then becomes a true representation of your domain and business logic.
The mapping of the DTO to your Domain Entity (search query) can be done in the Repository and the mapping of your Domain Entity to your DTO (save/update query) would also be done in your Repository.
To do your mapping you can either create custom mapping classes or use 3rd party tools like AutoMapper. I am a big fan of AutoMapper.
A sample code example would be along the lines of:
--Custom mapper
public class UserRepository : IUserRepository
{
private readonly IUserMapper _userMapper;
public UserRepository(IUserMapper userMapper)
{
_userMapper = userMapper;
}
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return _userMapper.MapUserDTOToDomainEntity(DtoUser);
}
}
public class UserMapper : IUserMapper
{
public Domain.User MapUserDTOToDomainEntity(DataEntity.User dtoUser)
{
//Manual property mapping
}
}
--AutoMapper Example
public class UserRepository : IUserRepository
{
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return Mapper.Map<Domain.User>(DtoUser);
}
}
Other examples include:
https://stackoverflow.com/questions/14724612
There are many many debates out there in blogs and here on SO about the value of DTO's,
including MSDN, this blog and these https://stackoverflow.com/questions/11237946, https://stackoverflow.com/questions/15148866

Entity Framework & RIA Services - CRUD on Link Table

After many hours, countless failures, I decided to change my Entity Model to include a link table in the model for each many-to-many relationship. This worked for me because RIA Services doesn't support many-to-many relationships.
Regardless, I'm able to build, but do not have any idea how to manage these relationships within the application itself. Should I create methods on the Domain Service, that are hidden from the client and used to perform CRUD operations on the link table objects?
An example would be greatly appreciated, thanks in advance.
I guess you already know http://m2m4ria.codeplex.com/ that adds many to many support to wcf ria services, however if you want to manage it by yourself, you better send it to the client and treat them like any other entities. You will not have Entity A with a collection of B entities and entities B with a collection of A entitities but rather:
public class A
{
int Id {get; set;}
ICollection<A_To_B> B_Entities {get; private set;}
}
public class A_To_B
{
int Id {get; set;}
A EntityA {get; set;}
int id_A {get; set;}
B EntityB {get; set;}
int id_B {get; set;}
}
public class B
{
int Id {get; set;}
ICollection<A_To_B> A_Entities {get; private set;}
}
in your domain service add methods to correctly expose all of these entities and don't forget to properly decorate them (relationship is straight 1:m)
This is indeed a nuisance.
I've not tried m2m4ria and do it manually on the client, ie. I expose the bridge table in the domain service. Sometimes it turns out to be a good idea anyway if the bridge table is later elevated to carry more data.
To ease the pain of managing the bridge table on the client I've written some helper you might want to consider yourself.
public interface ILinkEntity
where LinkEntity : Entity, ILinkEntity
where SourceEntity : Entity, ILinkedSourceEntity
where TargetEntity : Entity
{
SourceEntity Source { get; set; }
TargetEntity Target { get; set; }
}
public interface ILinkedSourceEntity
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity
where TargetEntity : Entity
{
EntityCollection Links { get; }
ObservableCollection Targets { get; set; }
}
public static class ManyToManyHelper
{
public static void UpdateLinks(this ILinkedSourceEntity source, EntitySet set)
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity, new()
where TargetEntity : Entity
{
if (!(source is SourceEntity)) throw new Exception("Expected source to be a SourceEntity.");
var toAdd = (
from target in source.Targets
where source.Links.FirstOrDefault(le => le.Target.Equals(target)) == null
select target
).ToArray();
foreach (var target in toAdd) source.Links.Add(new LinkEntity() { Source = source as SourceEntity, Target = target });
var toRemove = (
from link in source.Links
where source.Targets.FirstOrDefault(te => te.Equals(link.Target)) == null
select link
).ToArray();
foreach (var link in toRemove)
{
source.Links.Remove(link);
// This can happen when the entities had not yet been added to the context.
set.Remove(link);
}
}
public static void UpdateTargets(this ILinkedSourceEntity source)
where SourceEntity : Entity, ILinkedSourceEntity
where LinkEntity : Entity, ILinkEntity, new()
where TargetEntity : Entity
{
if (source.Targets == null)
{
source.Targets = new ObservableCollection();
}
else
{
source.Targets.Clear();
}
foreach (var link in source.Links) source.Targets.Add(link.Target);
}
}
I have this in a file called ManyToManyUtils and it should live somewhere where your domain entities can reference them (so typically in the domain client project).
I then augment the respective auto-generated domain entities to support those interfaces, eg. like this:
public partial class Question : ILinkedSourceEntity
{
EntityCollection ILinkedSourceEntity.Links
{
get { return QuestionCategories; }
}
public ObservableCollection Categories { get; set; }
ObservableCollection ILinkedSourceEntity.Targets
{
get { return Categories; }
set { Categories = value; }
}
}
public partial class QuestionCategory : ILinkEntity
{
Question ILinkEntity.Source { get { return Question; } set { Question = value; } }
Category ILinkEntity.Target { get { return Category; } set { Category = value; } }
}
public partial class Category
{
}
So in this example each Question can be in many categories. Category as a domain entity needs not to be modified.
I usually augment domain entity classes with properties frequently anyway, so I often already have those partial classes.
Now I can bind views against those new collection properties. However, I still need to call the helper update methods to sync the bridge table with those helper collection properties.
So after each load or refresh from the domain services you have to call:
myQuestion.UpdateTargets();
And after each edit by the user (eg from a SelectionChanged handler in the view, or - if you are happy with the consequences - just before you call SaveChanges), call:
myQuestion.UpdateLinks(myContext.QuestionCategories);
That way, the nastiness is factored out as much as possible.

Populating Models using LINQ

I'm trying to figure out a clear way of populating my model classes from LINQ to SQL generated objects. My goal is to keep my Models and LinqModels separate. Say I have the following models:
public class Person {
public List<Account> Accounts {get; set;}
}
public class Account {
public List<Purchase> Purchases {get; set;}
}
public Purchase {
public String Whatever {get; set;}
}
Now, I also have nearly identical data models generated by LINQ to SQL. So if I want to populate a Person object I'm going to add a getter method within the DataContext partial class:
public Person GetPersonByID(int personID) {
....
}
How we populate this Person object and its children properties throughout the rest of the application is done like this:
public Person GetPersonByID(int personID) {
Person res =
from p in Persons
select new Person() {
Accounts = (
from a in p.Accounts
select new Account() {
Purchases = (
from m in p.Purchases
select new Purchase() {
Whatever = m.Whatever
}
).ToList()
}
).ToList()
}
return res;
}
So for each child property we need to extend the query. What I would really prefer is if I could do something more like this:
public Person GetPersonByID(int personID) {
return new Person( this.Persons.SingleOrDefault( p => p.ID == personID ) );
}
....
public class Person {
public Person(DataModels.Person p) {
Accounts = (from a in p.Accounts select new Account(a)).ToList();
}
}
public class Account {
public Account(DataModels.Account a) {
Purchases = (from r in a.Purchases select new Purchase(r)).ToList();
}
}
public class Purchase {
public Purchase(DataModels.Purchase r) {
Whatever = r.Whatever
}
}
This is much more manageable, but the initial GetPersonByID call does not return the data I need to populate these child objects. Is there any way around this?
Or is there a better alternative to populating model objects using LINQ to SQL?
*** Sorry if my code examples are not quite right*
What you are looking for is called "persistence ignorance".
It is a valued property of a design, specifically in the DDD (Domain Driven Design) circles.
You can achieve it for example using LinqToSQL's XML mapping capabilities, where you do not generate data classes and indicate to LTS how to map your domain classes (Account, Purchase etc) to the database directly.
Because of LinqToSQL's limited capabilities in terms of mapping options (specifically the lack of value objects, the limitation on the inheritance mapping and the lack of Many-to-Many relationship support), it might or might not work in your case.
Another option, if you have your LTS-generated classes and your domain classes as above, is to look into Automapper, which can help getting some of the repetitive work out of the way.

Resources