Inserting Data into Linked Repositories in ATG - atg

I have a requirement in which I have two tables employee in ABC repository
and address_details in XYZ repository.
One column of employee has a foreign key reference to address_details.
Here, I am having the primaryKey for address_details and with that primaryKey
reference I have to insert my data in employee.
So my RDF goes something like this:
RDF 1: (Repository1 : ABC)
<item-descriptor name=”employee” >
<table name=”employee”>
<property name=”empId” data-type=”string” column-name=”emp_id”
required=”true”/>
<property name=”address” column-name=”address_id” item-type=”address”
repository=”XYZ” required=”true”/>
</table>
</item-descriptor>
RDF 2: (Repsitory2 : XYZ)
<item-descriptor name=”address” >
<table name=”address_details”>
<property name=”addressId” data-type=”string” column-name=”address_id”/>
<property name=”streetName” column-name=”street_name” data-type=”string”/>
<property name=”city” column-name=”city” data-type=”string” />
</table>
</item-descriptor>
I have all the addresses stored in table address_details. And I have to
map employee to these addresses.
The way which I am trying here is fetching the RepostoryItem of Address
first, then setting the property-type address of employee and adding it
into employee table. This works.
But I want to insert the employee data in one call alone?
Any suggestions on how can I do that using RepositoryItem or
MutableRepositoryItem?

By insert in one call, I'm assuming you mean you want to commit all of the inserts atomically. There is no mechanism to do multiple inserts in one SQL statement -- you'll have to call MutableRepository.addItem() once for each item you have created. The following code will allow you to wrap your repository work in a transaction, so that the data is all committed at once.
TransactionManager tm = ...
TransactionDemarcation td = new TransactionDemarcation ();
try {
try {
td.begin(tm);
// Create all items and call MutableRepository.addItem() for each of them.
}
finally {
td.end();
}
}
catch (TransactionDemarcationException exc) {
logError(exc);
}

Related

LINQ expression to get the whole content of right table

In my database, I have these two tables with a relationship :
I would like to get the whole content of the "assignee_kanban" column in "assigneekanban" table (which for now contains six names).
Here is the expression I use (in my "Kanban" controller using entity framework) :
public List<Kanban> LoadCard() {
return _context.Kanbans.Include(c => c.IdAssigneeKanbanNavigation).ToList();}
When I try to get the result in my razor page with :
#foreach (var name in Kanbans)
{
<tr>
<td>#name.IdAssigneeKanbanNavigation.AssigneeKanban1</td>
</tr>
}
unfortunatly, the result I get contains only three names : the three names corresponding to the three "id_assignee_kanban" that exist in the "kanban" table.
How can I get all the names contained in the "assignee_kanban" column ?
(I succeed to get the values using assigneekanban controller but for some reason, I want to use kanban controller with the navigation statement)
(project webassembly blazor using .net 6 aspnet hosted)
Thank you for your help.
Here is the content of the "kanban" table (I removed some no important columns for this problem) :
Here is the content of the "assigneekanban" table :
Here is the output :
As we can see, the name "Robert" corresponding to the id n°5 doesn't appaer in the result and the other names appear as many time they exist in the kanban table (of course, I can add a distinct close to avoid duplicate names but it doesn't bring the missing name !).
You need a second query to get all entries from the assigneekanban table. Your current implementation will only get those values from the assigneekanban that have a foreign key entry in the kanban table (Basically doing an INNER JOIN).
public async Task<List<Kanban>> LoadCardAsync()
{
return _context.Kanbans.ToList();
}
public async Task<List<AssigneeKanban>> LoadAssigneesAsync()
{
return _context.AssigneeKanbans.ToList();
}
public async Task LoadEverythingAsync()
{
Kanbans = await LoadCardAsync();
Assignees = await LoadAssigneesAsync();
}
Then in your Razor Page
#foreach (var assignee in Assignees)
{
<tr>
<td>#assignee.AssigneeKanban1</td>
</tr>
}

Mybatis collection with multiple columns

I have a table which has three foreign keys to items. These corresponding objects I want in a list property. I have the following collection mapping
<collection property="items" column="{item1Id, item2Id, item3Id}">
<association property="exampleNestedItem" column="{id, ###itemId###}" select="com.example.mapper.getItem" />
</collection>
I need the current value at ###itemId###. How can I reference the columns "item1Id", "item2Id" and "item3Id" for this Parameter?
I ended up with a very easy solution. In my case I know that there will always be 3 elements in that list. So I added a setter for each element in the model class like this
public void setElement1(Element element) {
elements.add(element);
}
...
and I added an association for each element
<association property="element1" column="element1Id" select="com.example.mapper.getItemWithId"/>
...
It will for sure not scale for many elements, but for my case it fits!

Entity Framework, how to treat a view as a child table

I have a table, call it Transaction, and a view, call it TransactionExtra, which is based on Transaction, e.g., create view TransactionExtra select t.id as t_id, x.* from Transaction t join X x on ....
In Entity Framework, I'd like to be able to access TransactionExtras objects from Transaction objects, ("create a navigation property") e.g., transaction.TransactionExtra, just as if TransactionExtra were a table with a foreign key to T.
How can I do this in the EDMX visual editor?
At present I'm doing it manually:
static TransactionExtra extra(Entities db, transaction t)
{
return db.TransactionExtra.Where(x => x.t_id == t.id).FirstOrDefault();
}
For every Transaction there is zero or one TransactionExtra.
I can't seem to figure out how to tell EntityFrameworkEDMX to map the property.
Thanks.

Breeze with stored procedure CLR error

Im trying to call a stored procedure using Entity framework.
If I go direcly to the web api method it works fine, but when calling it from breeze it causes an exception on the metadata method.
The error is :
"Could not find the CLR type for...".
Anyone know how to fix this?
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.

Entity framework - inserting by ID

I'm in a situation where I'm importing lots of "link" records from an XML file, and I want to insert them in my SQL link table using Entity Framework. My link table is literally just 2 columns, both of which are FKs and constitute the PK:
[UserAssessmentId] [int] NOT NULL
[AnswerId] [int] NOT NULL
The way I'm used to doing inserts involves the following:
Get the UserAssessment entity from the DB for userAssessmentId.
Get the Answer entity from the DB for answerId.
Add the Answer entity to the UserAssessment entity's Answers collection.
Repeat 2 and 3 for each answerId to add.
Call context.SaveChanges().
The trouble is that this is extremely DB intensive when adding hundreds of answers; EF has to get the record for each answer it is adding to the link table! I just want to insert a record with a given userAssessmentId, and a given answerId, and not go through the trouble of getting the entity first. EF needn't worry about whether the IDs I'm inserting are valid; just assume they are. Is there a way to get EF to do this or do I need to just use plain SQL?
The simplest option would probably be to create a separate context and a simple entity to represent your link table.
[Table("Name of the link table")]
public class UserAssessmentAnswer
{
public int UserAssessmentId { get; set; }
public int AnswerId { get; set; }
}
public class UserAssessmentAnswerContext : DbContext
{
public UserAssessmentAnswerContext()
: base("Connection string for the real context")
{
}
public IDbSet<UserAssessmentAnswer> UserAssessmentAnswers
{
get { return Set<UserAssessmentAnswer>(); }
}
}
Then you can use the new context and entity to insert your data:
using (var context = new UserAssessmentAnswerContext())
{
context.UserAssessmentAnswers.Add(new UserAssessmentAnswer
{
UserAssessmentId = ...,
AnswerId = ...
});
...
context.SaveChanges();
}
EDIT
You'll need to turn off database initialization for the new context. In your configuration file, add:
<entityFramework>
<contexts>
<context
type="YourNamespace.UserAssessmentAnswerContext, YourAssembly"
disableDatabaseInitialization="true"
/>
</contexts>
</entityFramework>
Or, you can add the following code to your startup:
Database.SetInitializer<UserAssessmentAnswerContext>(null);