Question about using Anonymous List Types - asp.net

private List<T> GetFieldList()
{
var Fields = new { DisplayName = "MCP", FieldName = "t.MCP", FieldType = 1 };
var FieldList = (new[] { Fields }).ToList();
return FieldList;
}
Should I be able to do something like this?

If I understand correctly your tag "asp.net" this construction will be used as part of data binding.
Just use non generic :
private IList GetFieldList()
{
var Fields = new { DisplayName = "MCP", FieldName = "t.MCP", FieldType = 1 };
IList FieldList = (new[] { Fields }).ToList();
return FieldList;
}
It would be nice handled by all data-bound controls.

I just realized I don't need to use an anonymous list as I know the structure of the data I'm expecting, so I'll just create a small class for it.

Related

Entity Framework 6 .add() with variable table and column name

I am able to get a somewhat dynamic Entity Framework search result with the following simplified example, which pulls a single result from the DB or Cache:
string strTableName = "TableName2"
string strColumnName = "MyColumnName"
int intPrimaryKey = 1
Type returnType;
returnType = typeof(TableName1);
string queryResults = null;
switch (strTableName)
{
case "TableName2":
returnType = typeof(TableName2);
break;
}
var refColumnName = returnType.GetProperty(strColumnName );
var query = mydbEntity.Set(returnType).Find(intPrimaryKey );
var queryResults = refColumnName.GetValue(query).ToString();
This can also be adapted for Updating a record:
DataQuery.LeadsEntity.Entry(query).Property(strColumnName ).CurrentValue = "Whatever";
DataQuery.LeadsEntity.SaveChanges();
Is there an equivalent for way for .set(returnType).Add()? I'm not sure if there is a way to do this type of thinking using variable table and column names:
DataQuery.LeadsEntity.Set(returnType).Add(new returnType { PrimayKeyName = 1, refColumnName = "Something" });
If you don't know a priori what's the name of the primary key property, it could be a little painful to get it from the type.
This is the way I found more reliable to retrieve the primary key from the entity type:
private string[] GetKeyNames(DbContext context, Type entityType)
{
ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
//create method CreateObjectSet with the generic parameter of the base-type
MethodInfo method = typeof(ObjectContext).GetMethod("CreateObjectSet", Type.EmptyTypes)
.MakeGenericMethod(entityType);
dynamic objectSet = method.Invoke(objectContext, null);
IEnumerable<dynamic> keyMembers = objectSet.EntitySet.ElementType.KeyMembers;
string[] keyNames = keyMembers.Select(k => (string)k.Name).ToArray();
_keyNamesCache[entityType] = keyNames;
return keyNames;
}
But assuming your primary keys are always a single property, you could use reflection to create the entity object and set its properties like this:
private void CreateEntity(Type entityType, object pkValue, Dictionary<string, object> Columns)
{
// Create the new entity
var entity = Activator.CreateInstance(entityType);
// Get the primary key property name
var pkName = GetKeyNames(context, entityType).First();
// Set Pk value
entityType.GetProperty(pkName).SetValue(entity, pkValue);
// Set other column(s)
foreach (var col in Columns)
{
entityType.GetProperty(col.Key).SetValue(entity, col.Value);
}
// Add the entity to the DbSet
using (var context = new YourContext())
{
context.Set(entityType).Add(entity);
}
}

DeExpress MVC 17.1 How populate TokenBox from a database

I want populate a TokenBox from a database using the property tokenBoxSettings.Properties.DataSource
TokenBoxView.cshtml
groupSettings.Items.Add(
formLayoutSettings.Items.Add(i =>
{
i.FieldName = "email";
i.Caption = "Email";
i.NestedExtensionType = FormLayoutNestedExtensionItemType.TokenBox;
TokenBoxSettings tokenBoxSettings = (TokenBoxSettings) i.NestedExtensionSettings;
tokenBoxSettings.Width = 350;
//data binding
tokenBoxSettings.Properties.DataSource = mainController.GetMails();
tokenBoxSettings.Properties.TextField = "email_empresarial";
tokenBoxSettings.Properties.ValueField = "email_empresarial";
tokenBoxSettings.Properties.IncrementalFilteringMode = IncrementalFilteringMode.Contains;
tokenBoxSettings.Properties.ValueSeparator = ';';
})
);
TokenBoxController.cs
//mainController
//I created a dictionary based on the result of select
public Dictionary<string, string> GetMails()
{
var email = db.usuario.ToList().Select(e => new { e.email_empresarial });
var emails = new Dictionary<string, string>();
foreach (var mail in email)
{
correos.Add(mail.ToString(), mail.ToString());
}
return emails;
}
But it shows me the "object explicitly", I only need the value, for example kenneth or manuel
tokenBox list
What am I doing wrong? or with what other approach I can do?
You are specifying same email_empresarial field name for both tokenBoxSettings.Properties.TextField and tokenBoxSettings.Properties.ValueField.
Since you are binding your TokenBox to Dictionary, try changing settings for TextField and ValueField to reference Dictionary Key and Value, like this:
tokenBoxSettings.Properties.TextField = "Value";
tokenBoxSettings.Properties.ValueField = "Key";
Also, in your GetMail() method you have declared the var emails but in the loop you are adding items to the undeclared correos variable. Are you sure you don't have a bug here?
Another note, in the Dictionary returned by GetMails() you populate both dictionary keys and values with the same value of mail.ToString(). Are you sure you really need to use Dictionary to bind your TokenBox? If keys and values are equal you may try going with plain List<string>.

LINQ dynamic property in select

// Hi everyone
i do this call in Action :
[HttpGet]
public virtual ActionResult JsonGetProvinces(int countryId)
{
//WebSiteContext WbContext = new WebSiteContext();
//UnitOfWork UnitofWork = new UnitOfWork(WbContext);
var provinces =
(
from province in unitofWork.ProvinceRepository.All
where province.CountryId == countryId
select new
{
Id = province.Id,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
}
).ToList();
return Json(provinces, JsonRequestBehavior.AllowGet);
}
something is wrong with my query :
var provinces =
(
from province in unitofWork.ProvinceRepository.All
where province.CountryId == countryId
select new
{
Id = province.Id,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
}
).ToList();
Particulary,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
In BDD, there is Name_fr, Name_en columns
and i'm trying to take one dynamically... Is it possible ?
Of course, i can take both and choose dynamically the column in View but i would to know how do...
Thank you for your help
The short answer is you need to change your code a bit and using expression tree inside. Look at this question
EF can not translate function calls to SQL. Using expression trees can be comlicated see this question
Here is a sample with expression trees. The GetQuery2 is the same as GetQuery but with expression tree and a propertyname parameter.
public static IQueryable<Foo> GetQuery(BlogContext context)
{
var query = from x in context.BlogEntries
select new Foo
{
NameX = x.Name
};
return query;
}
public static IQueryable<Foo> GetQuery2(BlogContext context, string propertyName)
{
ConstructorInfo ci = typeof(Foo).GetConstructor(new Type[0]);
MethodInfo miFooGetName = typeof(Foo).GetMethod("set_NameX");
MethodInfo miBlogEntry = typeof(BlogEntry).GetMethod("get_" + propertyName);
ParameterExpression param = Expression.Parameter(typeof(BlogEntry), "x");
IQueryable<Foo> result = Queryable.Select<BlogEntry, Foo>(
context.BlogEntries,
Expression.Lambda<Func<BlogEntry, Foo>>(
Expression.MemberInit(
Expression.New(ci, new Expression[0]),
new MemberBinding[]{
Expression.Bind(miFooGetName,
Expression.Property(param,
miBlogEntry))}
),
param
)
);
return result;
}
It is easier the fetch all all language strings and write an additional Property Name that does the magic.

Retrieve Arguments of a Workflow (with default values)?

Given is a Workflow Foundation 4 runtime that is working against a website ;)
We need to get the arguments of workflows to show the user an editor to enter the arguments. For that we need all arguments with names, types and - default values, as well as an indication whether an argument is required.
Workflows are stored as XAML files.
How to do that? The data seems to be in the Activity Metadata which seems to be not avaialble outside the Workflow. In addition, the Workflow Engine ModelService is for the Designer and has a lot of overhead.
Any easy way to retrieve this information?
I've already done something similar. Reflection might be your best (and only) option if you want a generic approach.
// Just an holder for InArgument informations
class InArgumentInfo
{
public string InArgumentName { get; set; }
public string InArgumentDescription { get; set; }
public bool InArgumentIsRequired { get; set; }
}
static ICollection<InArgumentInfo> GetInArgumentsInfos(Activity activity)
{
var properties = activity.GetType()
.GetProperties()
.Where(p => typeof(InArgument).IsAssignableFrom(p.PropertyType))
.ToList();
var argumentsCollection = new Collection<InArgumentInfo>();
foreach (var property in properties)
{
var descAttribute = property
.GetCustomAttributes(false)
.OfType<DescriptionAttribute>()
.FirstOrDefault();
string description = descAttribute != null && !string.IsNullOrEmpty(descAttribute.Description) ?
descAttribute.Description :
string.Empty;
bool isRequired = property
.GetCustomAttributes(false)
.OfType<RequiredArgumentAttribute>()
.Any();
argumentsCollection.Add(new InArgumentInfo
{
InArgumentName = property.Name,
InArgumentDescription = description,
InArgumentIsRequired = isRequired
});
}
return argumentsCollection;
}
This way you can not only retrieve the argument's name but also other information hold by the argument's attributes. For example I choose to give argument an user-friendly name through [Description] attribute (eg. instead of MyPropertyName user sees "My Property Name").
Note: if you can ensure that you activity is an ActivityBuilder or DynamicActivity they both have Properties property that you can use, but the principle is the same.
Load it as DynamicActivity and iterate over Properties property
var dynamicActivity = ActivityXamlServices.Load(foo) as DynamicActivity
foreach(DynamicActivityProperty prop in dynamicActivity.Properties)
{
// ...
}
UPDATE: Missed default value part
foreach (var prop in dynamicActivity .Properties)
{
object defaultValue;
if (prop.Value == null)
{
defaultValue = null;
}
else
{
Type genericTypeDefinition = prop.Type.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(InArgument<>) || genericTypeDefinition == typeof(InOutArgument<>))
{
var valueProp = prop.Value.GetType().GetProperty("Expression", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);
var expression = valueProp.GetValue(prop.Value, null);
var expressionValueProp = expression.GetType().GetProperty("Value");
defaultValue = expressionValueProp.GetValue(expression, null);
}
}
}
Not totally guaranteed, there are some checks you have to do.

EF 4.1 Code First adding to a foreign key collection

If I have an entity with a collection property for another entity. What is the best way to add a new entity and it's related entities? The problem I have is that the collection is initially null.
var form = new Form()
{
Name = "TestForm"
};
ctx.Forms.Add(form);
var formField = new FormField()
{
Name = "TestField"
};
form.FormFields.Add(formField);
ctx.SaveChanges();
The form.FormFields property above is null so I get an exception. I know I could set the relationship in the other direction but I haven't defined a Form property on FormFields (and I don't really want to).
So what is the cleanest solution to for this?
The simplest solution is to initialize the collection like this:
var form = new Form() {
Name = "TestForm"
};
ctx.Forms.Add(form);
var formField = new FormField() {
Name = "TestField"
};
if(form.FormFields == null)
form.FormFields = new List<FormField>();
form.FormFields.Add(formField);
ctx.SaveChanges();

Resources