Building a Repository using ServiceStack.ORMLite - repository-pattern

I'm using servicestack and i'm planning to use ormlite for the data access layer.
I've these tables (SQL Server 2005)
Table ITEM
ID PK
...
Table SUBITEM1
ID PK FK -> ITEM(ID)
...
Table SUBITEM2
ID PK FK -> ITEM(ID)
...
Table POST
ID PK
...
Table COMMENT
ID PK
...
Table DOWNLOAD
ID PK
...
Table POST_COMMENT
ID PK
POST_ID FK -> POST(ID)
COMMENT_ID FK -> COMMENT(ID)
Table DOWNLOAD_COMMENT
ID PK
DOWNLOAD_ID FK -> DOWNLOAD(ID)
COMMENT_ID FK -> COMMENT(ID)
I created a class for each table and mapped them using annotations (autoincrement, references, etc).
I decided to creare a repository for each "entity" (item, post, comment, download).
Each repository contains the basic CRUD logic,
eg. 1 CommentRepository has a Save(Comment comment, Object relationship) that performs db.Insert(comment, relationship) where relationship is PostComment or DownloadComment.
eg. 2 PostRepository has a Save(Post p) that performs the insert into POST.
I'm not sure about this solution because the repository interface is different and I can't do polymorphic queries.
Can you provide any advice to improve my DAL?
Thank you for your attention.

I'm not a fan of forced artificial abstraction so I don't like starting with a repository for every entity as it will just lead to un-necessary code-bloat. I like to start with only 1 repository for all entities encapsulating all data access and refactor naturally out when it gets too big.
I don't know enough of your domain to know what the best RDBMS layout is but I also like to avoid creating un-necessary tables where possible and will look to blob non-aggregate root data, e.g. if SubItem can only applies and is not meaningful outside the context of its parent Item, then I would just blob it saving a couple of tables, e.g:
class Item {
int Id; //PK, AutoIncr
List<SubItem> SubItem;
}
Rather than the separate Many : Many tables, I would just maintain it on the single Comment table, e.g:
class Comment {
int Id; //PK, AutoIncr
string CommentType; //i.e. Post or Download
int RefId;
string Comment;
}
So my repository would mimic the data access patterns required for fulfilling the Web Request, something like:
class BlogRepository {
void AddCommentToPost(int postId, Comment comment);
void AddCommentToDownload(int downloadId, Comment comment);
}

Related

OData action in data entity for table without natural key

In Dynamics 365 Finance and Operations, I created data entity for WMSOrderTrans table. Let's say it's SalesOrderPickingListLines. I've added EntityKey with two fields: orderId and RecId (the same index exists in the table itself, named OrderIdx).
The data entity works without an issue, key fields are in the metadata, I can get a record using data/SalesOrderPickingListLines(dataAreaId='inpl',orderId='myorder',RecId1=myrecordid)
The problem is, that now I need to create OData action for it, but it seems that that the key fields are not seen in the action. I am using Power Automate to test it.
I created a function in the entity's class with this code:
[SysODataActionAttribute('SetPickQuantity', true)]
public real setPickQuantity(InventQty _qty)
{
WMSOrderTrans _wmsOrderTrans;
select firstonly forupdate _wmsOrderTrans
where _wmsOrderTrans.orderId == this.orderId && _wmsOrderTrans.RecId == this.RecId1;
// some code to proceed
return _wmsOrderTrans.Qty;
}
The OData action is seen by Power Automate, but there are no key fields (except Company), so I am unable to perform this action for any record.
Usually it works without doing any other steps so that's why I'm here. The only difference with this and my previous work is that the source table (WMSOrderTrans) does not have a natural key, its index is RecId field. But I am not sure if this is the issue here. Any help will be appreciated.

DynamoDB LSI or GSI to query on composite attribute

I'm trying to use DynamoDB for my JAVA project and I have this (from my point of view) strange scenario that I have to cover. Let me to explain how I organize my table:
Suppose that I have to store these info related to Books:
book_id (UUID) used as PK autogerated
author_id (UUID)
type (String)
book_code (UUID) this different as concept from book_id
publishing_house_id (String)
book_gender (String)
And additional dynamic attributes that are not queryable and I'm thinking to store as Document (JSON)
Now, the queries that I need are:
Insert/Get/Update/Delete book by book_id
Get all book by author_id
Get all book by author_id and type
Get book by book_code, publishing_house_id, book_gender (I would like to highlight that this tuple will be unique)
Using the book_id as PK I'll be able to cover the first query set (CRUD using the book id)
For the query #2 and #3 the idea is to create a GS index where the author_id is the PK and type is the SK.
In order to cover the query #4 I'm thinking to:
Create an dedicated Attribute book_sk where I'll store:
book_gender#publishing_house_id#book_code
Create a Local Secondary Index using this book_sk as SK
Probably I can move book_code, publishing_house_id, book_gender into a Document field instead to have these unquerable attributes here.
I'm not very sure about this design.
What do you think?
In that case, is it better to use a LSI or GSI for the query #4?
For #4, if you're always getting a book by those three together, then make an attribute with that concatenated value and use it as the PK of a GSI, making it easy to directly look up.

How to save object in cfwheels and save data to an associated table with comma separated values out of an input field?

How do I save my object in cfwheels and add data out of a form input field in the form of a comma separated list and save this data in a related table?
My form passes the data to the controler in the params struct.
There is the field "tags" wich holds the values like "Apple,Pear,Banana".
How can I save this data to a second related table? Is it possible without a second query and without a transaction?
This is the simplified controller:
public void function create() {
news = model("News").new(params.news);
news.save()
}
The normal object data should go to the table
news
The related data to
tags
I created the associations in both models.
based on the info you have provided it's hard to give more feedback than this:
public void function create() {
news = model("News").new(params.news); //<- this is enough
// news.save() //<- not needed
}
You may need to include the post/get data, the models, as well as a description on what is the result and what is the expected result.

How to model lending items between a group of companies

I have a group of related companies that share items they own with one-another. Each item has a company that owns it and a company that has possession of it. Obviously, the company that owns the item can also have possession of it. Also, companies sometimes permanently transfer ownership of items instead of just lending it, so I have to allow for that as well.
I'm trying to decide how to model ownership and possession of the items. I have a Company table and an Item table.
Here are the options as I see them:
Inventory table with entries for each Item - Company relationship. Has a company field pointing to a Company and has Boolean fields is_owner and has_possession.
Inventory table with entries for each Item. Has an owner_company field and a possessing_company field that each point to a Company.
Two separate tables: ItemOwner and ItemHolder**.
So far I'm leaning towards option three, but the tables are so similar it feels like duplication. Option two would have only one row per item (cleaner than option one in this regard), but having two fields on one table that both reference the Company table doesn't smell right (and it's messy to draw in an ER diagram!).
Database design is not my specialty (I've mostly used non-relational databases), so I don't know what the best practice would be in this situation. Additionally, I'm brand new to Python and Django, so there might be an obvious idiom or pattern I'm missing out on.
What is the best way to model this without Company and Item being polluted by knowledge of ownership and possession? Or am I missing the point by wanting to keep my models so segregated? What is the Pythonic way?
Update
I've realized I'm focusing too much on database design. Would it be wise to just write good OO code and let Django's ORM do it's thing?
Is there a reason why you don't want your item to contain the relationship information? It feels like the owner and possessor are attributes of the item.
class Company(models.Model):
pass
class Item(models.Model):
...
owner = models.ForeignKey(Company, related_name='owned_items')
holder = models.ForeignKey(Company, related_name='held_items')
Some examples:
company_a = Company.objects.get(pk=1)
company_a.owned_items.all()
company_a.held_items.all()
items_owned_and_held_by_a=Items.objects.filter(owner=company_a, holder=company_a)
items_on_loan_by_a=Items.objects.filter(owner=company_a).exclude(holder=company_a)
#or
items_on_loan_by_a=company_a.owned_items.exclude(holder=company_a)
items_a_is_borrowing=Items.objects.exclude(owner=company_a).filter(holder=company_a)
#or
items_a_is_borrowing=company_a.held_items.exclude(owner=company_a)
company_b = Company.objects.get(pk=2)
items_owned_by_a_held_by_b=Items.objects.filter(owner=company_a, holder=company_b)
#or
items_owned_by_a_held_by_b=company_a.owned_items.filter(holder=company_b)
#or
items_owned_by_a_held_by_b=company_b.held_items.filter(owner=company_a)
I think if your items are only owned by a single company and held by a single company, a separate table shouldn't be needed. If the items can have multiple ownership or multiple holders, a m2m table through an inventory table would make more sense.
class Inventory(models.Model):
REL = (('O','Owns'),('P','Possesses'))
item = models.ForeignKey(Item)
company = models.ForeignKey(Company)
relation = models.CharField(max_length=1,choices=REL)
Could be one implementation, instead of using booleans. So I'd go for the first. This could even serve as an intermediate table if you ever decide to use a 'through' to relate items to company like this:
Company:
items = models.ManyToManyField(Item, through=Inventory)
Option #1 is probably the cleanest choice. An Item has only one owner company and is possessed by only one possessing company.
Put two FK to Company in Item, and remember to explicitly define the related_name of the two inverses to be different each other.
As you want to avoid touching the Item model, either add the FKs from outside, like in field.contribute_to_class(), or put a new model with a one-to-one rel to Item, plus the foreign keys.
The second method is easier to implement but the first will be more natural to use once implemented.

Grouping Custom Attributes in a Query

I have an application that allows for "contacts" to be made completely customized. My method of doing that is letting the administrator setup all of the fields allowed for the contact. My database is as follows:
Contacts
id
active
lastactive
created_on
Fields
id
label
FieldValues
id
fieldid
contactid
response
So the contact table only tells whether they are active and their identifier; the fields tables only holds the label of the field and identifier, and the fieldvalues table is what actually holds the data for contacts (name, address, etc.)
So this setup has worked just fine for me up until now. The client would like to be able to pull a cumulative report, but say state of all the contacts in a certain city. Effectively the data would have to look like the following
California (from fields table)
Costa Mesa - (from fields table) 5 - (counted in fieldvalues table)
Newport 2
Connecticut
Wallingford 2
Clinton 2
Berlin 5
The state field might be id 6 and the city field might be id 4. I don't know if I have just been looking at this code way to long to figure it out or what,
The SQL to create those three tables can be found at https://s3.amazonaws.com/davejlong/Contact.sql
You've got an Entity Attribute Value (EAV) model. Use the field and fieldvalue tables for searching only - the WHERE caluse. Then make life easier by keeping the full entity's data in a CLOB off the main table (e.g. Contacts.data) in a serialized format (WDDX is good for this). Read the data column out, deserialize, and work with on the server side. This is much easier than the myriad of joins you'd need to do otherwise to reproduce the fully hydrated entity from an EAV setup.