Nullable Guid Parameter in RAW method Codefluent Entities - codefluent

I have a RAW method for an entity that has GUIDS as parameters.
LOADONE (Guid CwObjectGuid, Guid CountryGuid) RAW
With the corresponding body:
SELECT * FROM dbo.Bid
WHERE Bid_CwObject_Guid = #CwObjectGuid
AND ((Bid_CountryGuid = #CountryGuid) OR (#CountryGuid = '00000000-0000-0000-0000-000000000000' AND Bid_CountryGuid IS NULL))
The parameter CountryGuid can be a default Guid. However, the method that is generated checks whether the parameter is a default. In that case the method will return NULL.
if ((countryGuid.Equals(CodeFluentPersistence.DefaultGuidValue) == true))
{
return null;
}
I don't want that check. Can I somehow prevent it?

By default, the property is not nullable, so CodeFluent check if the value is equals to the default value (see Simon's answer). You can disable this behavior by setting usePersistenceDefaultValue to false:
<cf:method name="load" body="LOADONE(...) RAW" rawBody="...">
<cf:parameter name="countryGuid" usePersistenceDefaultValue="false"/>
</cf:method>
You can also send nullable guid to the database
<cf:method name="load" body="LOADONE(Guid? id) RAW" rawBody="..." />

Related

Transient annotation and error executing DDL

I use the annotation # trasient to declare a boolean variable but when I start my spring application, I got the error as below
Error executing DDL "
alter table categories
add column has_children boolean not null" via JDBC Statement
This indicates that the column of has_children should not be null but Im not sure how to set the default of boolean value to false. Any ideas ? Thanks
----Edit-----
Below is my entity code
#Transient
private boolean hasChildren;
public boolean isHasChildren() {
return hasChildren;
}
public void setHasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
You didn't provide the code showing the entity, but just a heads up.
The default value of a boolean (primitive) is false, but the default value of a Boolean (the wrapper class) is null.
So it's worth checking if your variable has_children is created using Boolean instead of boolean

How to find foreign key field for navigation property?

For a given entity I can get all its references by calling
var references = dbContext.Entry(entity).References;
Now I want to set all references to null.
foreach (var reference in references)
{
reference.CurrentValue = null;
}
context.Update(entity);
context.SaveChanges();
But apparently it is not sufficient to set the reference to null, one must set the foreign key property as well. But how to find the foreign key field for a given reference?
You can use Metadata property to get the associated INavigation, then ForeignKey property to get the associated IForeignKey, then the Properties property to get the associated properties of type IProperty, and finally the Name property which can be passed to Property method to obtain the associated PropertyEntry for manipulating the value.
Putting all that in action:
var entry = dbContext.Entry(entity);
foreach (var reference in entry.References)
{
reference.CurrentValue = null;
foreach (var fkProperty in reference.Metadata.ForeignKey.Properties)
entry.Property(fkProperty.Name).CurrentValue = null;
}

How to get the maximum length of a string from an EDMX model in code?

I've created an EDMX object from a database I'm programming against.
I need to get input from a user and save it to a row in the database table. The problem is that I need to limit the length of input strings to the width of the corresponding VARCHAR column in the database.
When I browse the model, I can clearly see in the properties window that the model knows the max length of the string, but I don't know how to access this data in code.
If I want to write something like this:
Entities entities = new Entities();
myTable = entities.myTable.First();
if (userInput.length > myTable.columnA.MaxLength)
{
// tell the user that the input is too long.
}
else
{
myTable.columnA = userInput;
}
How do I write it?
Update: I would like to point out that the IObjectContextAdapater mentioned in the answers below is in the System.Data.Entity.Infrastructure namespace.
Here are two methods by which you can read the meta data:
int? GetMaxLength(DbContext context, string tableName, string propertyName)
{
var oc = ((IObjectContextAdapter)context).ObjectContext;
return oc.MetadataWorkspace.GetItems(DataSpace.CSpace).OfType<EntityType>()
.Where(et => et.Name == tableName)
.SelectMany(et => et.Properties.Where(p => p.Name == propertyName))
.Select (p => p.MaxLength)
.FirstOrDefault();
}
int? GetMaxLength<T>(DbContext context, Expression<Func<T, object>> property)
{
var memberExpression = (MemberExpression)property.Body;
string propertyName = memberExpression.Member.Name;
return GetMaxLength(context, typeof(T).Name, propertyName);
}
So you can either enter the table name and property name, or an expression that specifies the property you're interested in.
Another approach could be to create a MetaData class and use the MaxLength attribute.
It's not very pretty; reading edmx properties at runtime is not something Microsoft exposed easily or documented well (or in some cases, at all). context is your DBContext.
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var entityType = objectContext.MetadataWorkspace.GetItems<EntityType>(DataSpace.CSpace).Where(e => e.Name == "your entity name").First();
var facets = entityType.Properties["your property name"].TypeUsage.Facets;
facets will look something like this, so you'll need to look for the MaxLength Name(may not exist, depending on the underlying field type) and get the Value:
Count = 5
[0]: Nullable=false
[1]: DefaultValue=null
[2]: MaxLength=250
[3]: Unicode=false
[4]: FixedLength=false
If you modify the T4 template you can add your own attribute to the properties that have MaxLength set.
If you can find the right place to add it, it's something as simple as this:
var lengthAttributeText = edmProperty.MaxLength.HasValue
? string.Format("[MaxLength({0})] ", edmProperty.MaxLength.Value)
: "";
And then add this into the text for the property line. (Tricky to be more detailed since I've already modified my .tt file a lot; also the lack of proper IDE support for .tt files makes this a lot harder than it could be.)

Entity Framework Self-Referencial Many-To-Many with Payload ( Bill of Materials BOM )

I asked this question a while back without an answer, I believe it may be the most bizarre implementation for the EF, although it is quite practical. Here is my previous post:
Entity Framework Self Referencing Hierarchical Many To Many
I've decided to ask again with the additional keyword Payload and a clearer understanding.
In the Apress publication: Entity Framework 4.0 Recipes: A Problem-Solution Approach, recipe 2-6 on pg. 26 is titled Modeling a Many-To-Many Relationship with a Payload. Recipe 2-7 is titled Modeling a Self-Referential Relationship.
Reading that would give you a foundation for what my problem is, the difference is that I have a Self-Referential Many-To-Many with Payload which is not discussed in the book or anywhere in the universe to my knowledge.
To put it very simply I have a Resource table with ID and Type fields. I also have a ResourceHierarchy table which serves as the junction or bridge table in that it has a composite primary key made up of a Parent_ID and Child_ID and a composite foreign key. So a Resource entity can either serve as a Child Resource or Parent Resource or BOTH.
By now the Entity Framework would have generated the Resource Entity but the ResourceHierarchy Entity would actually be hidden from the EDMX Designer since in the EDMX file it is being treated as only a relationship and not an entity.
The generated Resource Entity will have navigation properties like Resources and Resources1 which I renamed Parents and Children.
So I can write code like this: (It doesn't do anything I'm just showing some examples)
List<Resource> listResources = Context.Resouces.ToList()
foreach (Resource resc in listResources)
{
List<Resource> listParents = resc.Parents.ToList()
List<Resource> listChildren = resc.Children.ToList()
foreach (Resource parent in listParents)
{
Console.WriteLine(parent.Type);
}
foreach (Resource child in listChildren)
{
Console.WriteLine(child.Type);
}
resc.Children.Add(new Resource());
Console.WriteLine(resc.Parents.First().Children.First().Type);
}
Lets say I have a Resource that is being shared by two other Resouces. The two other resources would be the Parents of said Resource. Said Resource is also the only Child of each of it's Parents. Yes, a Resource can have three or more "Parents", even two dads if you like but would ancestors share a child? Not on my watch. So anyway... we have to think of this from a real world scenario for it to make sense from this point on.
Here is some code to get us started:
Resource parent1 = new Resource();
Resource parent2 = new Resource();
Resource child = new Resource();
parent1.Type = "WidgetA";
parent2.Type = "WidgetB";
child.Type = "1/4 Screw"
parent1.Children.Add(child);
parent2.Children.Add(child);
Product product1 = new Product();
Product product2 = new Product();
product1.Resources.Add(parent1);
product2.Resources.Add(parent2);
So we have two widgets that have a screw.
WidgetA and WidgetB are listed as products on a website. What if WidgetA sells, what will happen to WidgetB's screw? So now you see we need a Quantity property on the Resource Entity.
Fast forward many months to were I currently am in my project and assume the fetal position after realizing how limited the EF is.
This part gets a little more complicated. If
child.Quantity = 4
parent1.Quantity = 1
parent2.Quantity = 1
How will we know or set it up so that we can assign 2 of the child to parent1 and 2 of the child to parent2?
That can only be done via adding another quantity(int) column which we'll call "Required" to the ResourceHierarchy table so it would look like:
Parent_ID int not null,
Child_ID int not null,
Required int not null default 1
So we've attached the payload to the ResourceHierarchy Entity in the db. If we regenerate the model from the EDMX designer ResourceHierarchy is no longer a Relationship but is now an Entity. If I choose instead to only Refresh the ResourceHierarchy table from the EDMX designer I can see the Required property in the Storage Model but it is no where in the Conceptual or Mapping models since the ResourceHierarchy would be a relationship. However if I delete the Resource table and the ResourceHierarchy table and regenerate them the ResourceHierarchy table is now visible with the Required column and it is now an Entity.
It is possible to work with this setup but it's so much more difficult than simply being able to access the ResourceHierarchy Relationship and retrieve the Required property. Even if the ResourceHierarchy EntityType includes the Required property in the Storage Model I cannot access the Required property from code after accessing the AssociationSet. If the ResourceHierarchy table is a relationship in the EF it looks like this in the Storage Model.
<EntityType Name="ResourceHierarchy">
<Key>
<PropertyRef Name="Parent_ID" />
<PropertyRef Name="Child_ID" />
</Key>
<Property Name="Parent_ID" Type="int" Nullable="false" />
<Property Name="Child_ID" Type="int" Nullable="false" />
<Property Name="Required" Type="int" Nullable="false" />
</EntityType>
If I try to merge the generated EDMX files I get the error telling me that the ResourceHierarchy can either be an Entity or a Relationship but not both.
This is called a Many-To-Many with Payload. Trying to implement this with a Self-Referential Hierarchy is a nightmare in the EF. I'm working with VS2010, SQL 2008, and the .NET 4.0 Framework.
The concept is that I want to have Products that are made up of Resources which themselves are made up of other Resources or serve to make up other Resources and each one requires a certain quantity amount of Resources. It's basically a Bill of Materials BOM. Does the EF not support the BOM model?
Would the new HIERARCHYID feature in SQL Server 2008 help by any chance?
So I ended up with a surprisingly graceful solution.
CREATE TABLE Resource
(
ID INT NOT NULL,
Type VARCHAR(25) NOT NULL
)
ALTER TABLE Resource
ADD CONSTRAINT PK_Resource PRIMARY KEY (ID)
CREATE TABLE ResourceHierarchy
(
Ancestor_ID INT NOT NULL,
Descendant_ID INT NOT NULL,
Required INT NOT NULL DEFAULT 1
)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT PK_ResourceHierarchy PRIMARY KEY (Ancestor_ID, Descendant_ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Ancestors FOREIGN KEY (Ancestor_ID) REFERENCES Resource (ID)
ALTER TABLE ResourceHierarchy
ADD CONSTRAINT FK_Descendants FOREIGN KEY (Descendant_ID) REFERENCES Resource (ID)
When the EDMX was generated I renamed the Resource Entity navigation properties from ResourceHierarchy to DescendantRelationships and ResourceHierarchy1 to AncestorRelationships. I then renamed the ResourceHierarchy Entity navigation properties from Resource to Descendant and Resource1 to Ancestor.
Whereas before I could write code like this:
Resource resource = new Resource();
resource.Descendants.Add(new Resource());
foreach (Resource descendant in resource.descendants)
{
descendant.Type = "Brawr";
List<Resource> ancestors = descendant.Ancestors.ToList();
}
Of course this approach did not allow me to access the Required property.
Now I must do the following:
Resource ancestor = new Resource();
Resource descendant = new Resource();
ResourceHierarchy rh = new ResourceHierarchy { Ancestor = ancestor, Descendant = descendant, Required = 1 };
ancestor.DescendantRelationships.Add(rh);
But check it out I can now get to the Required property like so:
int req = ancestor.DescendantRelationships.First().Required;
One might rename the Required field to RequiredDescendants since Descendants don't need a required amount of Ancestors, only Ancestors need to specify how many Descendants are required.
So it's a hop, but a graceful one.
Please let me know your thoughts, especially if I've overlooked a gotcha or something.
Something to watch out for...
When we want to add a descendant to a resource we need to remember that DescendantRelationships gives us the hierarchy where the referenced resource is acting as descendants to other resources.
So in order to add a descendant to a resource we must do the following:
Resource resource = new Resource { Type = "WidgetA" };
Resource descendant = new Resource { Type = "Screw" };
resource.AncestorRelationships.Add(new ResourceHierarchy { Descendant = descendant, Required = 1 };
Of course this all depends on how you name your navigation properties, I'm just saying be careful. AncestorRelationships would be the go to navigation property in order to add descendants and vice versa. A better thing to do might be to rename AncestorRelationships to AncestorRoles and DescendantRelationships to DescendantRoles.
AncestorRoles would translate to ResourceHierarchiesWhereCurrentResourceIsAnAncestor.
DescendantRoles would translate to ResourceHierarchiesWhereCurrentResourceIsADescendant.
So we could do:
// print descendant types
foreach (ResourceHierarchy rh in resource.AncestorRoles)
{
Console.WriteLine(rh.Descendant.ResourceType.Type);
}
Sorry to change up the nomenclature so much but I think it helps understand what's going on.
The MSDN Libary link : http://msdn.microsoft.com/en-us/library/ms742451.aspx is titled PropertyPath XAML Syntax and has a section titled Source Traversal (Binding to Hierarchies of Collections)
This is the HierarchicalDataTemplate I want to use:
<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=AncestorRoles/Descendant}">
<CustomControls:ResourceTreeItem Type="{Binding ResourceType.Type}"/>
</HierarchicalDataTemplate>
Only the first Resource is displayed. After the following code runs the TreeView shows one ResourceTreeItem in the TreeView.
ObservableCollection<Resource> Resources = new ObservableCollection<Resource>
Resources.Add(new Resource { ResourceType.Type = "WidgetA" });
MyTreeView.ItemsSource = Resources;
So that works. However when I run the following code the TreeView is not updated.
Resource resource = MyTreeView.Items[0] as Resource;
resource.AncestorRoles.Add( new ResourceHierarchy { Descendant = new Resource { ResourceType = "Screw" }, Required = 1 } )
Even if I get the CollectionViewSource of the TreeView.ItemsSource and call Refresh() it doesn't show up. I triple checked the relationships and it's all there.
I think it's a bug with the PropertyPath Traversal syntax.
The solution was to add a TreeParent property to the Resource partial class declaration and utilize 3 ValueConverters which is a long story but it's because the datacontext naturally alternates from a Resource to a ResourceHierarchy. The RequiredConverter is the one that checks the TreeParent and finds the Required property Payload.
class ValidatorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Resource resource = value as Resource;
ResourceHierarchy rh = value as ResourceHierarchy;
if (resource != null)
{
value = resource;
}
else if (rh != null)
{
value = rh.Descendant;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
class ResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Resource resource = value as Resource;
ResourceHierarchy hierarchy = value as ResourceHierarchy;
if (resource != null)
{
if (resource.AncestorRoles.Count > 0)
{
value = resource.AncestorRoles;
}
else
{
value = resource;
}
}
else if (hierarchy != null)
{
value = hierarchy.Descendant.AncestorRoles;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
class RequiredConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Resource resource = (Resource)value;
Resource parent = ((Resource)value).TreeParent as Resource;
if (parent != null)
{
value = parent.AncestorRoles.Where(p => p.Descendant == resource).First().Required;
}
else
{
value = 0;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And here is the final HierarchicalDataTemplate:
<HierarchicalDataTemplate DataType="{x:Type Inventory:Resource}" ItemsSource="{Binding Path=., Converter={StaticResource resourceconv}}">
<StackPanel DataContext="{Binding Path=., Converter={StaticResource validatorconv}}">
<CustomControls:ResourceTreeItem Required="{Binding Path=., Converter={StaticResource requiredconv}}" Free="{Binding Free}" OnHand="{Binding OnHand, Mode=TwoWay}" Type="{Binding ResourceType.Type}"/>
</StackPanel>
</HierarchicalDataTemplate>
The StackPanel only serves to add another DataContext layer. I left in the Free, OnHand and Type properties so you could see that 3 properties are receiving their binding from the StackPanels DataContext and the Required property is doing it's thing like a mad man.
So the moral is if you need a Payload maybe the EF isn't for you.

Setting ModelState values in custom model binder

I am using custom model binder in ASP.NET MVC 2 that looks like this:
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
BaseContentObject obj = (BaseContentObject)base.BindModel(controllerContext, bindingContext);
if(string.IsNullOrWhiteSpace(obj.Slug))
{
// creating new object
obj.Created = obj.Modified = DateTime.Now;
obj.ModifiedBy = obj.CreatedBy = controllerContext.HttpContext.User.Identity.Name;
// slug is not provided thru UI, derivate it from Title; property setter removes chars that are not allowed
obj.Slug = obj.Title;
ModelStateDictionary modelStateDictionary = bindingContext.ModelState;
modelStateDictionary.SetModelValue("Slug", new ValueProviderResult(obj.Slug, obj.Slug, null));
...
When I get back from this binder into controller action, my business object that is provided as a parameter to the action is correctly altered (the lines obj.Created = .... work).
However, the ModelState is not updated. I know this because I have Required on my business object's Slug property and although I altered ModelStateDictionary in my custom model binder, providing a Slug to it (as you can see above), the ModelState.IsValid is still false.
If I put ModelState["Slug"] in my Watch window in Debug session, it says it has Errors (1), so apparently it is empty and as such fails.
How can I correctly alter the ModelState inside the custom model binder code?
Apparently there is no way to revalidate the ModelState once you change a value of some key. The IsValid remains false because setting a new value to some key does not trigger revalidation.
The solution is to first remove the key that triggered IsValid to be false and recreate it and assign the value to it. When you do that the ModelState automatically revalidates and if everything is fine, IsValid returns true.
Like this:
bindingContext.ModelState.Remove("Slug");
bindingContext.ModelState.Add("Slug", new ModelState());
bindingContext.ModelState.SetModelValue("Slug", new ValueProviderResult(obj.Slug, obj.Slug, null));