EF Core 2.2.3 child record is not saved after update from 2.2.1 - asp.net-core-2.0

I had the below .net Core code working with Microsoft.EntityFrameworkCore.SqlServer 2.2.1.
After I upgrade the dotnet core sdk to 2.2.3 it is not working.
Note that the related entity is not mapped with a FK in DB. I have a partial class that has the relation and has the attribute NotMapped to make this work in 2.2.1 .
I am not sure what changed and what I need to add to save header and detail record.
var soHeader = new masSoHeader();
var orderToAdd = Mapper.Map(salesOrder.SalesOrderHeader, soHeader);
orderToAdd.InsertDateTime = DateTime.Now;
var newSalesOrder = _context.masSoHeader.Add(orderToAdd);
var newSoSalesOrderDetails =
Mapper.Map<List<soSalesOrderDetail>>(salesOrder.SalesOrderDetails);
if (newSoSalesOrderDetails != null)
{
foreach (var soSalesOrderDetail in newSoSalesOrderDetails)
{
soSalesOrderDetail.InsertDateTime = DateTime.Now;
newSalesOrder.Entity.soSalesOrderDetail.Add(soSalesOrderDetail);
}
}
int numberOfRowsInserted = _context.SaveChanges();

Related

kentico add new form field via API

Hello Kentico experts,
I need to create some new form fields dynamically via Kentico API. I found a solution but it is for Kentico 6 and it is not available for my version (i'm using Kentico 8).
https://devnet.kentico.com/articles/how-to-add-a-new-field-to-a-document-type-using-api
Please help !
Thanks,
Duong
This should work:
string classname = "classname";
DataClassInfo dci = DataClassInfoProvider.GetDataClassInfo(classname);
if (dci != null)
{
FormInfo fi = new FormInfo(dci.ClassFormDefinition);
if (fi != null)
{
// Field definition
FormFieldInfo ffi = new FormFieldInfo();
ffi.Name = "FieldName";
ffi.AllowEmpty = true;
ffi.System = false;
ffi.FieldType = CMS.FormEngine.FormFieldControlTypeEnum.UploadControl;
ffi.Visible = true;
ffi.Caption = "Field Caption";
ffi.Enabled = true;
// Set whatever properties are relevant to you
fi.AddFormItem(ffi);
TableManager tm = new TableManager(null);
tm.AddTableColumn(dci.ClassTableName, ffi.Name, "uniqueidentifier", true, null);
dci.ClassXmlSchema = tm.GetXmlSchema(dci.ClassTableName);
dci.ClassFormDefinition = fi.GetXmlDefinition();
// Update DataClassInfo object
DataClassInfoProvider.SetDataClassInfo(dci);
// Update inherited classes with new field
FormHelper.UpdateInheritedClasses(dci);
}
}
You can always check the API changes between versions on Kentico DevNet.

Rewrite code for Automapper v5.0 to v4.0

Automapper v4.0 was very straight forward to use within a method, can someone help rewrite this for v5.0 please (specifically the Mapper code):
public IEnumerable<NotificationDto> GetNewNotifications()
{
var userId = User.Identity.GetUserId();
var notifications = _context.UserNotifications
.Where(un => un.UserId == userId && !un.IsRead)
.Select(un => un.Notification)
.Include(n => n.Gig.Artist)
.ToList();
Mapper.CreateMap<ApplicationUser, UserDto>();
Mapper.CreateMap<Gig, GigDto>();
Mapper.CreateMap<Notification, NotificationDto>();
return notifications.Select(Mapper.Map<Notification, NotificationDto>);
}
UPDATE:
It seems that EF Core doesn't project what AutoMapper is mapping with:
return notifications.Select(Mapper.Map<Notification, NotificationDto>);
But I do get results in Postman with the following code:
return notifications.Select(n => new NotificationDto()
{
DateTime = n.DateTime,
Gig = new GigDto()
{
Artist = new UserDto()
{
Id = n.Gig.Artist.Id,
Name = n.Gig.Artist.Name
},
DateTime = n.Gig.DateTime,
Id = n.Gig.Id,
IsCancelled = n.Gig.IsCancelled,
Venue = n.Gig.Venue
},
OriginalVenue = n.OriginalVenue,
OriginalDateTime = n.OriginalDateTime,
Type = n.Type
});
If you want to keep using static instance - the only change is in mapper initialization:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ApplicationUser, UserDto>();
cfg.CreateMap<Gig, GigDto>();
cfg.CreateMap<Notification, NotificationDto>();
});
Also you should run this code only once per AppDomain (somewhere on startup for example) and not every time you calling GetNewNotifications.

Update Modified field in Office 365

Is there any way to update the Modified field in Office 365? I have checked both CSOM and Batch update methods. But it's failed. Could anybody help me to update this field.
Before attempting to set Modified, Created, Editor, and Author fields for a list item you need to disable a couple of properties on the List, specifically EnableVersioning and for good measure ForceCheckout.
SharePoint Online prerequisite is the SharePointOnline CSOM:
.NET client API reference for SharePoint Online
Nuget - Microsoft.SharePointOnline.CSOM
using (var context = new ClientContext(webUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName,password);
var list = context.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemID);
var user = context.Web.EnsureUser(accountName);
context.Load(user);
context.Load(list);
context.Load(item);
context.ExecuteQuery();
// If the properties are enabled on the list then disable them
bool updateList = list.ForceCheckout || list.EnableVersioning;
if (list.ForceCheckout) list.ForceCheckout = false;
if (list.EnableVersioning) list.EnableVersioning = false;
if (updateList)
{
list.Update();
context.ExecuteQuery();
}
// Now set the fields that are normally locked
item["Modified"] = DateTime.Now;
item["Created"] = DateTime.Now.AddDays(-3);
item["Author"] = user.Id;
item["Editor"] = user.Id;
item.Update();
context.ExecuteQuery();
}
SharePoint CSOM API does not support system update (SystemUpdate method counterpart from SSOM API) but you could manipulate system fields like Modified By and Modified fields directly as demonstrated below.
Prerequisites: SharePoint Server 2013 Client Components SDK
using (var ctx = GetContext(webUri, userName, password))
{
//get List Item
var list = ctx.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemId);
//Retrieve User
var user = ctx.Web.EnsureUser(accountName);
ctx.Load(user);
ctx.ExecuteQuery();
//Update system fields
item["Modified"] = DateTime.Now.AddMonths(-6);
item["Created"] = DateTime.Now.AddYears(-1);
item["Editor"] = user.Id;
item["Author"] = user.Id;
item.Update();
ctx.ExecuteQuery();
}
where
public static ClientContext GetContext(Uri webUri, string userName, string password)
{
var securePassword = new SecureString();
foreach (var ch in password) securePassword.AppendChar(ch);
return new ClientContext(webUri) { Credentials = new SharePointOnlineCredentials(userName, securePassword) };
}
SharePoint CSOM API now support system update using UpdateOverwriteVersion method. This way you can modify Modified, Created, Author and Editor properties without changing the item Version. For example:
$file = Get-PnPFile -Url $FileUrl -AsListItem
##update file properties
$item["Modified"] = $FileModifiedDate
$item["Created"] = $FileCreatedDate
$item["Author"] = $FileCreatedByDest.ID
$item["Editor"] = $FileModifiedByDest.ID
$fileTest2.UpdateOverwriteVersion()
Invoke-PnPQuery
That should do the trick.

How to Insert/Update into Azure Table using Windows Azure SDK 2.0

I have multiple entities to be stored in the same physical Azure table. I'm trying to Insert/Merge the table entries from a file. I'm trying to find a way to do this w/o really serializing each property or for that matter creating a custom entities.
While trying the following code, I thought maybe I could use generic DynamicTableEntity. However, I'm not sure if it helps in an insert operation (most documentation is for replace/merge operations).
The error I get is
HResult=-2146233088
Message=Unexpected response code for operation : 0
Source=Microsoft.WindowsAzure.Storage
Any help is appreciated.
Here's an excerpt of my code
_tableClient = storageAccount.CreateCloudTableClient();
_table = _tableClient.GetTableReference("CloudlyPilot");
_table.CreateIfNotExists();
TableBatchOperation batch = new TableBatchOperation();
....
foreach (var pkGroup in result.Elements("PartitionGroup"))
{
foreach (var entity in pkGroup.Elements())
{
DynamicTableEntity tableEntity = new DynamicTableEntity();
string partitionKey = entity.Elements("PartitionKey").FirstOrDefault().Value;
string rowKey = entity.Elements("RowKey").FirstOrDefault().Value;
Dictionary<string, EntityProperty> props = new Dictionary<string, EntityProperty>();
//if (pkGroup.Attribute("name").Value == "CloudServices Page")
//{
// tableEntity = new CloudServicesGroupEntity (partitionKey, rowKey);
//}
//else
//{
// tableEntity = new CloudServiceDetailsEntity(partitionKey,rowKey);
//}
foreach (var element in entity.Elements())
{
tableEntity.Properties[element.Name.ToString()] = new EntityProperty(element.Value.ToString());
}
tableEntity.ETag = Guid.NewGuid().ToString();
tableEntity.Timestamp = new DateTimeOffset(DateTime.Now.ToUniversalTime());
//tableEntity.WriteEntity(/*WHERE TO GET AN OPERATION CONTEXT FROM?*/)
batch.InsertOrMerge(tableEntity);
}
_table.ExecuteBatch(batch);
batch.Clear();
}
Have you tried using DictionaryTableEntity? This class allows you to dynamically fill the entity as if it were a dictionary (similar to DynamicTableEntity). I tried something like your code and it works:
var batch = new TableBatchOperation();
var entity1 = new DictionaryTableEntity();
entity1.PartitionKey = "abc";
entity1.RowKey = Guid.NewGuid().ToString();
entity1.Add("name", "Steve");
batch.InsertOrMerge(entity1);
var entity2 = new DictionaryTableEntity();
entity2.PartitionKey = "abc";
entity2.RowKey = Guid.NewGuid().ToString();
entity2.Add("name", "Scott");
batch.InsertOrMerge(entity2);
table.ExecuteBatch(batch);
var entities = table.ExecuteQuery<DictionaryTableEntity>(new TableQuery<DictionaryTableEntity>());
One last thing, I see that you're setting the Timestamp and ETag yourself. Remove these two lines and try again.

Orchard CMS- Get the current Data Migration Record version number

Given the name of a Migrations class as a string, how can I get the current version number as stored in Orchard_Framework_DataMigrationRecord?
I can see Version in IExtensionManager, but that appears to just be the module version as defined in module.txt.
OK, so I've solved this myself-
I knew that Orchard must already be executing similar code to what I require when it fires off migration methods, so I created a new migrations file, and put a breakpoint on the Create() method. When the breakpoint hit, I looked up through the call stack to find DataMigrationManager in Orchard.Data.Migration. Everything I needed was in there, and if anyone else has similar requirements, I suggest they have a look at that class as a starting point.
This is pretty much lifted straight out of that class:
string moduleName="Your.Module.Name";
var migrations = GetDataMigrations(moduleName);
// apply update methods to each migration class for the module
var current = 0;
foreach (var migration in migrations)
{
// copy the objet for the Linq query
var tempMigration = migration;
// get current version for this migration
var dataMigrationRecord = GetDataMigrationRecord(tempMigration);
if (dataMigrationRecord != null)
{
current = dataMigrationRecord.Version.Value;
}
// do we need to call Create() ?
if (current == 0)
{
// try to resolve a Create method
var createMethod = GetCreateMethod(migration);
if (createMethod != null)
{
//create method has been written, but not executed!
current = (int)createMethod.Invoke(migration, new object[0]);
}
}
}
Context.Output.WriteLine("Version: {0}", current);
A couple of methods you may need:
private DataMigrationRecord GetDataMigrationRecord(IDataMigration tempMigration)
{
return _dataMigrationRepository.Table
.Where(dm => dm.DataMigrationClass == tempMigration.GetType().FullName)
.FirstOrDefault();
}
private static MethodInfo GetCreateMethod(IDataMigration dataMigration)
{
var methodInfo = dataMigration.GetType().GetMethod("Create", BindingFlags.Public | BindingFlags.Instance);
if (methodInfo != null && methodInfo.ReturnType == typeof(int))
{
return methodInfo;
}
return null;
}
Don't forget to inject any dependencies that you may need.

Resources