I have an issue, in my breeze metadatastore I have an entity A with a navigationProperty to entity B
I would like to prime data getting only few important properties of A and few ones for B by using the breeze query projection manager like this:
var eq = EntityQuery.from("A").**select("PROP1,PROP2,B.PROP1")**;
return EntityManager.executeQuery(eq)
I'm getting it in a plain object {PROP1 : VALUE, PROP2 : VALUE, B_PROP1 : VALUE} that I'd like to turn in a partial cached entity of type A with a nested entity B:
{
PROP1 : VALUE,
PROP2 : VALUE,
B : {PROP1 : VALUE}
}
How can I achieve it by using the jsonresultadapter?
I have no issue working at first level, but going deeper I have troubles.
in the method visitNode, by getting parseContext.EntityManger I was able to create a new entity B and add it as property in the root of node parameter
Related
I am doing a simple projection query in Breeze:
var p1 = new Predicate('ID', 'eq', articleID);
var p2 = new Predicate('isDeleted', '!=', true);
var p3 = new Predicate('isAutoSave', '!=', true);
var query = EntityQuery.from(entityNames.article)
.where(p1.and(p2.and(p3)))
.select('Code, Description, ImageFileName, Notes, SupplierDistance')
I then used the entity mapper to create a partial entity to put into an observable to return back to the function. All was good.
Then I realised I needed a country name from a related table, so I first tried ".expand" and was told that Breeze couldn't do "expand" and "select" simultaneously. No problem, will select the related record directly:
.select('Code, Description, Country.CountryName, ImageFileName, Notes, SupplierDistance')
But as there is no "Country_CountryName" property on the entity I am creating a partial of, the mapping fails (unsurprisingly) with an "undefined is not a function" error. How am I able to include the countryName field from the related table in this way where I cannot map the entity?
I tried stuffing the javascript object returned by the query into my observable but that fails with an "object is not a function" error so that's no good either.
I decided that the entity mapping was unnecessary in the end and reverted to a simple projection query where I manually handled the "expand".
So I have a class with a property like this:
public class Foo
{
[Column("GBBRSH")
public static string Gibberish { get; set;}
....
}
For saving data, I have it configured so that the update/insert statements use a custom function:
public static string GetTableColumnName(PropertyInfo property)
{
var type = typeof(ColumnAttribute);
var prop = property.GetCustomAttributes(type, false);
if (propr.Count() > 0)
return ((ColumnAttribute)prop.First()).Name;
return property.Name;
}
This handles fine, but I noticed that when I go to retrieve the data, it isn't actually pulling data back via the function for this particular column. I noticed that the other data present was pulled, but the column in question was the only field with data that didn't retrieve.
1) Is there a way to perhaps use the GetTableColumnName function for the retrieval part of Dapper?
2) Is there a way to force Dapper.NET to throw an exception if a scenario like this happens? I really don't want to have a false sense of security that everything is working as expected when it actually isn't (I get that I'm using mapping that Dapper.NET doesn't use by default, but I do want to set it up in that manner).
edit:
I'm looking in the SqlMapper source of Dapper and found:
private static IEnumerable<T> QueryInternal<T>(params) // my knowledge of generics is limited, but how does this work without a where T : object?
{
...
while (reader.Read())
{
yield return (T)func(reader);
}
...
}
so I learned about two things after finding this. Read up on Func and read up on yield (never used either before). My guess is that I need to pass reader.Read() to another function (that checks against column headers and inserts into objects appropriately) and yield return that?
You could change your select statement to work with aliases like "SELECT [Column("GBBRSH")] AS Gibberish" and provide a mapping between the attribute name and the poco property name.
That way, Dapper would fill the matching properties, since it only requires your POCO's to match the exact name of the column.
I'm implementing a domain tree structure using entity framework + mvc.
I use JSTree to present the org structure.
Note that in that model scheme i use the TypeID property both as a condition of my inheritance and as a property for DomainEntity.
This of corse throw the following error:
Error 3 Error 3032: Problem in mapping fragments starting at line
139:Condition member 'DomainEntities.EntityTypeID' with a condition
other than 'IsNull=False' is mapped. Either remove the condition on
DomainEntities.EntityTypeID or remove it from the mapping.
C:\Code\CamelotShiftManagement\CamelotShiftManagement\Models\CamelotDB.edmx 140 15 CamelotShiftManagement
lets say i will not use TypeID as a property and keep it as a condition for the inheritance association that will result in the following when i'll try to populate a tree of my domain entities:
foreach (var entity in entities)
{
JsTreeModel tree = new JsTreeModel()
{
attr = new JsTreeAttribute()
{
id = entity.EntityID.ToString(),
},
data = entity.EntityName
};
if (entity is OrganizatioanlUnit)
{
tree.attr.type = eNodeType.OrganizationalUnit;
}
if (entity is Calendar)
{
tree.attr.type = eNodeType.Calendar;
}
PopulateTree(entity, tree);
io_Node.children.Add(tree);
}
this code is not maintainable because when a new entity will be introduced i will have to change this code, if i could only access a property that will tell me the type of entity i'm dealing with .. :) .
Here is the dilemma:
If i use inheritances and TypeID as a condition for each inheritance i can not access it as a property of DomainEntity, that will require me to use switch-case against typof(entity) to determine what type i should send to my JSTree plugin because he expects a type identification for each node in his JSON, if i will not use inheritance i will loose the polymorphic capabilities.
It is not only polymorphism i am after.. there will be other methods and properties relevant only for the inherited entities and i can see some injections points in the future...
My original question is here.
Below is my updated code.
Public Function StockTransferItemRemove(removeRequest As StockTransferItemRequest) As StockTransferItemResponse Implements IStockTransferService.StockTransferItemRemove
' create your objects
Dim removeResponse = New StockTransferItemResponse
Dim stockTransfer As New StockTransfer
Dim stockTransferItem As New StockTransferItem
Try
' get the aggregate root
stockTransfer = _stockTransferRepository.FindBy(removeRequest.StockTransferID).FirstOrDefault
stockTransfer.RemoveItem(removeRequest.StockTransferItemView.Id)
_stockTransferRepository.Save(stockTransfer)
Dim count As Integer = _uow.WMSCommit()
If (count > 0) Then
' the object was saved succesfully
removeResponse.Success = True
Else
' the object was not saved successfully
removeResponse.BrokenRules.Add(New BusinessRule(String.Empty, String.Empty, Tags.Messages.Commit_Failed))
End If
Catch ex As Exception
' an unexpected error occured
removeResponse.BrokenRules.Add(New BusinessRule(String.Empty, String.Empty, ex.Message))
End Try
Return removeResponse
End Function
When the unit of work tries to commit it produces the following error message.
The operation failed: The relationship could not be changed because one or more of
the foreign-key properties is non-nullable. When a change is made to a relationship,
the related foreign-key property is set to a null value. If the foreign-key does not
support null values, a new relationship must be defined, the foreign-key property must
be assigned another non-null value, or the unrelated object must be deleted.
I know that when I use StockTransfer.RemoveItem() that it removes the item from the collection but it keeps the record in the database, which is why I am receiving the error.
Is there a way of removing the child object from an aggregate Root and persisting the aggregate root?
Im sorry for the unclear code but im a C# guy so trying to find my way in VB Code. You should use the .Clear() option on the entities link which you want to clear.
Example:
Company <> Employees
Company.Emplyees.Clear() removes all the records in the relation
table.
Thats an issue im having too. I dont know the pure solution, but i always have to delete it in the ef context manualy before saving changes. In your repository method for save You should check for entities which are in the ef context but not in aggregates collection and remove them from the dbset on the context.
Did you find a good solution? I have created a solution using a ParentAttribute and extending the DbContext SaveChanges or ValidateEntity. You can find my solution here.
The answer might be a little late but, this extension method on my data context called DataContext (which inherits from DbContext) worked for me using EF4.3.
public static void Delete<TEntity>(this DataContext context, IEnumerable<TEntity> entities) where TEntity : class, new()
{
foreach (var entity in entities)
{
context.Delete(entity);
}
}
public static void Delete<TEntity>(this DataContext context, TEntity entity) where TEntity : class, new()
{
var obj = context.Entry(entity);
if (obj.State == System.Data.EntityState.Detached)
{
context.Set(typeof(TEntity)).Attach(obj.Entity);
}
context.Set(typeof(TEntity)).Remove(obj.Entity);
}
And the data context class just for completeness.
public class DataContext : DbContext
{
public DbSet<MyPOCO> POCOs { get; set; }
...
}
I have the following sample code which gets a list of values from a table in the DB and binds them to a checkbox list.
var db = new DBContext();
db.Entity1.ToList().ForEach(
x => CheckBoxList1.Items.Add(new ListItem(x.Value, x.ID));
I have about 10 checkboxlists like these and I dont want to repeat the code. I'm trying to extract a method out of it and use it for all checkboxes. Is it possible to load an entity by a string name? Something like -
db.Load("Entity1").ToList().ForEach...
So I can pass in the entity name and the checkbox list and do the foreach loop in the method and bind the items, like this -
void BindValues(string entityName, CheckBoxList checkBoxList)
{
db.Load("Entity1").ToList().ForEach(
x => checkBoxList.Items.Add(new ListItem(x.Value, x.ID)));
}
Thank you.
In Code First the DbContext exposes a .Set() or .Set(Type) method to get a handle on the table. So assuming straight EF exposes the same, and you are happy to access your lists by their entity type rather than a string, this would work for you.