I'm creating a table using a EF migration such as:
this.CreateTable("Message",
c => new
{
Id = c.Long(nullable: false, identity: true, defaultValue: 0),
Subject = c.String(nullable: false, maxLength: 64),
Body = c.String(nullable: false, isMaxLength: true)
})
.PrimaryKey(c => c.Id)
.Index(c => c.Id, unique: true);
How can I define the Id field to be auto_increment? I'm pretty sure it has to be possible, but im just struggling to find out...
Thanks.
Ok, it seems that setting the property "identity: true" in field should be enough but for some reason the field is not defined as IDENTITY(1, 1).
Found a workaround in this post:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/33db16ac-e166-455f-a47b-1e5fe0557979/
And it worked for me like this:
Id = new ColumnModel(PrimitiveTypeKind.Int64) { IsNullable = false, IsIdentity = true },
Now its defining the column as IDENTITY(1, 1)
If you do want to automatically generate it in code, you could skip the annotation on the Id field and do something like below.
public abstract class AbstractContext : DbContext {
/// <summary>
/// Custom processing when saving entities in changetracker
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
// recommended to explicitly set New Guid for appropriate entities
foreach (var entry in ChangeTracker.Entries<ModelBase>().Where(e => e.State == EntityState.Added) ) {
// only generate if property isn't identity...
Type t = entry.Entity.GetType();
var info = t.GetProperty("Id").GetCustomAttributes(
typeof(DatabaseGeneratedAttribute), true).Cast<DatabaseGeneratedAttribute>().Single();
if (info.DatabaseGeneratedOption != DatabaseGeneratedOption.Identity) {
entry.Entity.Id = Guid.NewGuid(); // now we make it
}
}
return base.SaveChanges();
}
}
For more information check Working with Entity Keys
I got this from the link Which I showed above comment.
I hope this will help to you.
Related
documentation is very sparce and all i tried results in the deserializer injected but normal odata url's not working anymore.
https://github.com/OData/WebApi/issues/158 has solutions buut for 5.6.
The final relevant comment is:
#dbenzhuser - In that commit, look at ODataFormatterTests.cs for how
inject a custom deserializer/deserializer provider. You can still use
a custom DeserializerProvider but it's injected through DI instead of
injecting it through ODataMediaTypeFormatters.
which is quite meaningless. I tried the code there, but it breaks, as I said, the URL's.
Right now my Odata setup is simple:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddOData();
\UnitTest\Microsoft.AspNet.OData.Test.Shared\Formatter\ODataFormatterTests.cs
has examples to inject them (like in lines 379-383)
config.MapODataServiceRoute("IgnoredRouteName", null, builder =>
builder.AddService(Microsoft.OData.ServiceLifetime.Singleton, sp => ODataTestUtil.GetEdmModel())
.AddService<ODataSerializerProvider>(ServiceLifetime.Singleton, sp => new CustomSerializerProvider())
.AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp =>
ODataRoutingConventions.CreateDefaultWithAttributeRouting("IgnoredRouteName", config)));
but I seem unable to get this working without removing the core odata routing.
Anyone an idea how to use that for the current version without breaking the base functionality?
There are three steps if you want to maintain the base functionality:
Your DeserializerProvider implementation should default to the base implementation for all scenarios that your custom Deserializer can't manage. In the following example the custom deserializer only operates on Resources and not Sets:
public class EntityTypeDeserializerProvider : DefaultODataDeserializerProvider
{
private readonly DataContractDeserializer _dataContractDeserializer;
public EntityTypeDeserializerProvider(IServiceProvider rootContainer)
: base(rootContainer)
{
_dataContractDeserializer = new DataContractDeserializer(this);
}
public override ODataEdmTypeDeserializer GetEdmTypeDeserializer(IEdmTypeReference edmType)
{
if(edmType.Definition.TypeKind == EdmTypeKind.Complex || edmType.Definition.TypeKind == EdmTypeKind.Entity)
return _dataContractDeserializer;
else
return base.GetEdmTypeDeserializer(edmType);
}
}
As with the provider your custom _Deserializer should call through to the base implementation for everything that you do not need to customize. In the following implementation we are only trying to enforce the Order of the properties that are deserialized as well as calling the DataContract OnDeserializing and OnDeserialized methods, the rest of the deserialization is unaffected:
/// <summary>
/// OData serializer that oberys the DataMember Order Attribute and OnDeserializing and OnDeserialized attributes on the resource definition
/// </summary>
public class DataContractDeserializer : ODataResourceDeserializer
{
public DataContractDeserializer(ODataDeserializerProvider provider)
: base(provider) { }
public override object CreateResourceInstance(IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
{
var resource = base.CreateResourceInstance(structuredType, readContext);
var type = resource.GetType();
if(type.GetCustomAttributesData().Any(x => x.AttributeType == typeof(DataContractAttribute)))
{
// manually call OnDeserializing
var init = type.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).FirstOrDefault(x => x.GetCustomAttributesData().Any(a => a.AttributeType == typeof(OnDeserializingAttribute)));
if(init != null)
{
init.Invoke(resource, new object[] { new StreamingContext(StreamingContextStates.Remoting, readContext ) });
}
}
return resource;
}
public override object ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
{
var resource = base.ReadResource(resourceWrapper, structuredType, readContext);
var type = resource.GetType();
if (type.GetCustomAttributesData().Any(x => x.AttributeType == typeof(DataContractAttribute)))
{
// manually call OnDeserialized
var final = type.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).FirstOrDefault(x => x.GetCustomAttributesData().Any(a => a.AttributeType == typeof(OnDeserializedAttribute)));
if (final != null)
{
final.Invoke(resource, new object[] { new StreamingContext(StreamingContextStates.Remoting, readContext) });
}
}
return resource;
}
public override void ApplyStructuralProperties(object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
{
var type = resource.GetType();
var memberDescriptors = type.GetProperties().Where(x => x.HasAttribute<DataMemberAttribute>());
if (memberDescriptors.Any())
{
var orderedProperties = from p in resourceWrapper.Resource.Properties
let clsProperty = memberDescriptors.FirstOrDefault(m => m.Name == p.Name)
let memberAtt = (DataMemberAttribute)(clsProperty?.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(DataMemberAttribute)))
orderby (memberAtt?.Order).GetValueOrDefault()
select p;
foreach (var property in orderedProperties)
{
ApplyStructuralProperty(resource, property, structuredType, readContext);
}
}
else
base.ApplyStructuralProperties(resource, resourceWrapper, structuredType, readContext);
}
}
Finally, You need to replace the default DeserializerProvider registration with your own, the following is an example of an overload to MapODataServiceRoute that registers the DeserializerProvider from the previous 2 examples.
I have commented out an example of registering a specific SerializerProvider
private static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName,
string routePrefix, IEdmModel model, ODataBatchHandler batchHandler = null, ODataUriResolver uriResolver = null, IList<IODataRoutingConvention> routingConventions = null)
{
return configuration.MapODataServiceRoute(routeName, routePrefix, builder =>
builder
.AddService(ServiceLifetime.Singleton, sp => model)
//.AddService<ODataSerializerProvider>(ServiceLifetime.Singleton, sp => new DefaultODataSerializerProvider(sp))
.AddService<ODataDeserializerProvider>(ServiceLifetime.Singleton, sp => new EntityTypeDeserializerProvider(sp))
.AddService(ServiceLifetime.Singleton, sp => batchHandler ?? new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer))
.AddService(ServiceLifetime.Singleton, sp => uriResolver ?? new ODataUriResolver())
.AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp =>
routingConventions ??
ODataRoutingConventions.CreateDefaultWithAttributeRouting(routeName, configuration)
)
);
}
I'm starting with Nancy, and I've run into a frustrating issue.
I have a model that has an ID (amongst other properties).
public class MyModel
{
public string Id { get; set; }
// other properties
}
In my module, I defined a PUT method
Put["/{id}", true] = async (parameters, token) =>
{
var model = this.Bind<MyModel>();
string id = parameters["id"];
if (model.Id != id)
return new Response
{
ReasonPhrase = $"[error message about IDs not matching]",
StatusCode = HttpStatusCode.BadRequest
};
await _myModelService.Update(model);
return Nancy.Response.NoBody;
};
The issue I'm experiencing is that at the this.Bind<MyModel>() call, Nancy overwrites the ID in the body with the ID in the route, meaning I can't test my "unmatched" scenario. For example:
PUT /orders/someObjectId
{
"Id" : "aDifferentObjectId"
}
binds to a MyModel with Id as "someObjectId".
I've also tried blacklisting the property:
this.Bind<MyModel>(m => m.Id)
this.Bind<MyModel>("id")
this.Bind<MyModel>("Id")
this.Bind<MyModel>("id", "Id")
However, this results in the bind operation clearing the ID property in the model.
How can I get exactly what's in the body?
Nevermind. I was doing something wrong, and now it's working without the blacklist. I have no explanation.
I have an enum class and I bind its values to Kendo DropDownListFor in Create mode without any problem. In Edit mode, these values are bound to Kendo DropDownListFor as well, but the current value's index is not selected. I mean that the record's IdentityType is Passport, but DropDownList shows "Please Select" as in Create mode. How can I fix it?
Note: When using #Html.DropDownListFor instead of Kendo().DropDownListFor it works, but I want to perform this by using Kendo().DropDownListFor.
Enum (IdentityType):
public enum IdentityType
{
[Description("Identity Card")]
IdentityCard= 1,
[Description("Driver License")]
DriverLicense= 2,
[Description("Passport ")]
Passport = 3
}
Enum Helper Method:
/// <summary>
/// For displaying enum descriptions instead of enum names on grid, ddl, etc.
/// </summary>
public static string GetDescription<T>(this T enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
View:
#(Html.Kendo().DropDownListFor(m => m.IdentityType)
.HtmlAttributes(new { #class = "k-dropdown" })
.OptionLabel("Please select").BindTo(Enum.GetValues(
typeof(Enums.IdentityType)).Cast<Enums.IdentityType>()
.Select(x => new SelectListItem { Text = x.GetDescription(), Value = x.ToString() }))
)
//This works but I want to perform this by uisng Kendo().DropDownListFor:
#Html.DropDownListFor(x => x.IdentityType,
new SelectList(Enum.GetNames(typeof(Enums.IdentityType)), new { #class = "k-dropdown" }))
I faced same problem, and the only solution i found is to set manually value:
#(Html.Kendo().DropDownListFor(m => m.IdentityType)
...
.Value(Model.IdentityType.ToString())
)
I've this configure() function in my form:
public function configure() {
$this->current_user = sfContext::getInstance()->getUser()->getGuardUser();
unset($this['updated_at'], $this['created_at']);
$this->widgetSchema['idempresa'] = new sfWidgetFormInputHidden();
$id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();
$this->setDefault('idempresa', $id_empresa);
$this->widgetSchema['no_emisor'] = new sfWidgetFormDoctrineChoice(array('model' => 'SdrivingEmisor', 'add_empty' => 'Seleccione un Emisor', 'expanded' => false, 'multiple' => false));
$this->validatorSchema['idempresa'] = new sfValidatorPass();
$this->validatorSchema['no_emisor'] = new sfValidatorPass();
}
And I'm need to define a relation data in save() function so I do this:
public function save($con = null) {
$new_machine = parent::save($con);
$relation = new SdrivingMaquinaEmisor();
$relation->setIdmaquina($new_machine);
$relation->setIdemisor();
$relation->save();
return $new_machine;
}
In order the set the Idemisor, how do I access to the selected value when users submit the form? Is this the best way to achieve this?
EDIT
After take the suggestion about how to access no_emisor value now my code looks like:
public function save($con = null) {
$new_machine = parent::save($con);
$relation = new SdrivingMaquinaEmisor();
$relation->setIdmaquina($new_machine);
$relation->setIdemisor($this->values['no_emisor']);
$relation->save();
return $new_machine;
}
But I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'idmaquina' cannot be null
For some reason $new_machine doesn't return the id of the latest saved element. Maybe I'm doing in the wrong way so what I'm doing wrong?
I think you might want to do this in the form's doUpdateObject instead, since that receives the cleaned values.
http://www.symfony-project.org/api/1_4/sfFormObject#method_doupdateobject
Edit:
Alternatively, $this->values['no_emisor'] should work once the form has been bound.
I have a DropDownList that contains the correct items and values when the view is rendered but the selected value is not being saved within the designated entity field Garage. Currently the value being saved and returned is 0 (None) in both create or edit post methods. I'm sure this is something simple but I can't figure it out... Thanks in advance!
The Model Class:
public enum GarageType { None = 0, One = 1, Two = 2, Three = 3, Four = 4 }
public int Garage { get; set; }
[NotMapped]
public GarageType GarageEnumValue
{
get { return (GarageType)Garage; }
set{ Garage = (int)value; }
}
The Control Create and Edit methods both look like this:
var statuses = from Property.GarageType s in Enum.GetValues(typeof(Property.GarageType))
select new { ID = (int)s, Name = s.ToString() };
ViewBag.GarageId = new SelectList(statuses, "ID", "Name", statuses.FirstOrDefault().ID);
Last the View:
#Html.DropDownList("GarageId", String.Empty)
Use the following overload of DropDownList method
#Html.DropDownList("GarageEnumValue", (SelectList)ViewBag.GarageId, String.Empty)
If you have a strongly type model use
#Html.DropDownListFor(m => m.GarageEnumValue, (SelectList)ViewBag.GarageId, String.Empty)
The first argument in both cases should be the property that you are going to bind the list.