public class MyInfo
{
public string Status { get; set; }
public string Class { get; set; }
public string FriendlyName { get; set; }
public string InstanceId { get; set; }
}
string strScript = "Get-PnpDevice";
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(strScript);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
foreach (PSObject pSObject in results)
{
}
After JsonConvert.SerializeObject(pSObject);
{"CliXml":"<Objs Version=\"1.1.0.1\" xmlns=\"http://schemas.microsoft.com/powershell/2004/04\">\r\n <S>_x000D__x000A_Status Class FriendlyName InstanceId _x000D__x000A_------ ----- ------------ ---------- _x000D__x000A_Unknown HIDClass HID-compliant consumer control device HID\\VID_0..._x000D__x000A_OK System System board ACPI\\PNP0..._x000D__x000A_OK System Motherboard resources ACPI\\PNP0..._x000D__x000A_OK System Motherboard resources SWD\\MSRRA..._x000D__x000A_Unknown HIDClass HID-compliant vendor-defined device HID\\VID_0..._x000D__x000A__x000D__x000A__x000D__x000A_</S>\r\n</Objs>"}
But I need is MyClasss.Class so i can diferentiate or make some condition on it .
1 => Create this classes
public class HardwareDevice
{
public string Name { get; set; }
public List<HardwareProperty> Properties { get; set; }
public HardwareDevice()
{
Properties = new List<HardwareProperty>();
}
}
public class HardwareProperty
{
public string Name { get; set; }
public string Value { get; set; }
}
2 = > Call this method which return List
var hardware = GetHardwareInfo(string "select * from Get-PnpDevice", string scope = "ROOT\\CIMV2")
3 = > here is the method
List<HardwareDevice> GetHardwareInfos(string query, string scope = "ROOT\\CIMV2")
{
List<HardwareDevice> hardwares = new List<HardwareDevice>();
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject share in searcher.Get())
{
HardwareDevice hrd = new HardwareDevice();
try
{
if (share["Name"] != null)
hrd.Name = share["Name"].ToString().Trim();
else
hrd.Name = share.ToString().Trim();
}
catch
{
hrd.Name = share.ToString().Trim();
}
foreach (PropertyData PC in share.Properties)
{
HardwareProperty property = new HardwareProperty();
property.Name = PC.Name;
if (PC.Value != null && PC.Value.ToString() != "")
{
switch (PC.Value.GetType().ToString())
{
case "System.String[]":
string[] str = (string[])PC.Value;
string str2 = "";
foreach (string st in str)
str2 += st + "&";
property.Value = str2.Trim('&');
break;
case "System.UInt16[]":
ushort[] shortData = (ushort[])PC.Value;
string tstr2 = "";
for (int i = 0; i < shortData.Length; i++)
{
tstr2 += shortData[i].ToString() + "&";
}
property.Value = tstr2.Trim('&');
break;
default:
property.Value = PC.Value.ToString().Trim();
break;
}
}
hrd.Properties.Add(property);
}
hardwares.Add(hrd);
}
}
catch (Exception exp)
{
}
return hardwares;
}
Related
I'm trying to do a JSON post call using a List property (RecurrenceException) but once the AddAppointment() method is called, RecurrenceException will always be null as its supposed to be but I get this exception on my API controller:
Microsoft.Data.SqlClient.SqlException: 'The parameterized query '(#PK int,#Title nvarchar(8),#Description nvarchar(8),#StartDate ' expects the parameter '#RecurrenceException', which was not supplied.'
Below is my client Razor Page code:
async Task AddAppointment(SchedulerCreateEventArgs e)
{
UvwHolidayPlanner holidayPlannerItem = e.Item as UvwHolidayPlanner;
List<DateTime> lst = new List<DateTime>();
holidayPlanner.Pk = holidayPlannerItem.Pk;
holidayPlanner.Title = holidayPlannerItem.Title;
holidayPlanner.Description = holidayPlannerItem.Description;
holidayPlanner.StartDate = holidayPlannerItem.StartDate;
holidayPlanner.EndDate = holidayPlannerItem.EndDate;
holidayPlanner.IsAllDay = holidayPlannerItem.IsAllDay;
if (holidayPlannerItem.RecurrenceRule == null)
{
holidayPlanner.RecurrenceRule = " ";
}
else
{
holidayPlanner.RecurrenceRule = holidayPlannerItem.RecurrenceRule;
}
holidayPlanner.RecurrenceException = holidayPlannerItem.RecurrenceException;
holidayPlanner.RecurrenceId = holidayPlannerItem.RecurrenceId;
await http.CreateClient("ClientSettings").PostAsJsonAsync<UvwHolidayPlanner>($"{_URL}/api/HolidayPlannerOperations/HolidayPlanner", holidayPlanner);
HolidayPlanners = (await http.CreateClient("ClientSettings").GetFromJsonAsync<List<UvwHolidayPlanner>>($"{_URL}/api/lookup/HolidayPlanner"))
.OrderBy(t => t.Title)
.ToList();
StateHasChanged();
}
Below is my class code:
public class UvwHolidayPlanner
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool IsAllDay { get; set; }
public int Pk { get; set; }
public string RecurrenceRule { get; set; }
public List<DateTime> RecurrenceException { get; set; }
public int RecurrenceId { get; set; }
}
And below is my API controller code:
[HttpPost]
[Route("HolidayPlanner")]
public void Post([FromBody] UvwHolidayPlanner item)
{
string SQLSTE = "EXEC [dbo].[usp_AddHolidayPlanner] #PK, #Title, #Description, #StartDate, #EndDate, #IsAllDay, #RecurrenceRule, #RecurrenceException, #RecurrenceId";
using (var context = new TestAppContext())
{
List<SqlParameter> param = new List<SqlParameter>
{
new SqlParameter { ParameterName = "#PK", Value = item.Pk },
new SqlParameter { ParameterName = "#Title", Value = item.Title },
new SqlParameter { ParameterName = "#Description", Value = item.Description },
new SqlParameter { ParameterName = "#StartDate", Value = item.StartDate },
new SqlParameter { ParameterName = "#EndDate", Value = item.EndDate },
new SqlParameter { ParameterName = "#IsAllDay", Value = item.IsAllDay },
new SqlParameter { ParameterName = "#RecurrenceRule", Value = item.RecurrenceRule },
new SqlParameter { ParameterName = "#RecurrenceException", Value = item.RecurrenceException },
new SqlParameter { ParameterName = "#RecurrenceId", Value = item.RecurrenceId }
};
context.Database.ExecuteSqlRaw(SQLSTE, param);
}
}
I'm trying to get the Audit:NET EntityFramework.Core extension to write an AuditLog entry per changed property.
For this purpose I've overidden the EntityFrameworkDataProvider.InsertEvent with a custom DataProvider.
The problem is, using DbContextHelper.Core.CreateAuditEvent to create a new EntityFrameworkEvent returns null.
The reason seems to be, at this point in the code execution DbContextHelper.GetModifiedEntries determines all EF Entries have State.Unmodified, even if they are clearly included in the EventEntry changes.
I'm trying to circumvent CreateAuditEvent by manually creating the contents is impossible due to private/internal properties.
Maybe there is an alternative solution to this problem I'm not seeing, i'm open to all suggestions.
Audit entity class
public class AuditLog
{
public int Id { get; set; }
public string Description { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
public string PropertyName { get; set; }
public DateTime AuditDateTime { get; set; }
public Guid? AuditIssuerUserId { get; set; }
public string AuditAction { get; set; }
public string TableName { get; set; }
public int TablePK { get; set; }
}
Startup configuration
Audit.Core.Configuration.Setup()
.UseCustomProvider(new CustomEntityFrameworkDataProvider(x => x
.AuditEntityAction<AuditLog>((ev, ent, auditEntity) =>
{
auditEntity.AuditDateTime = DateTime.Now;
auditEntity.AuditAction = ent.Action;
foreach(var change in ent.Changes)
{
auditEntity.OldValue = change.OriginalValue.ToString();
auditEntity.NewValue = change.NewValue.ToString();
auditEntity.PropertyName = change.ColumnName;
}
}
Custom data provider class
public class CustomEntityFrameworkDataProvider : EntityFrameworkDataProvider
{
public override object InsertEvent(AuditEvent auditEvent)
{
var auditEventEf = auditEvent as AuditEventEntityFramework;
if (auditEventEf == null)
return null;
object result = null;
foreach (var entry in auditEventEf.EntityFrameworkEvent.Entries)
{
if (entry.Changes == null || entry.Changes.Count == 0)
continue;
foreach (var change in entry.Changes)
{
var contextHelper = new DbContextHelper();
var newEfEvent = contextHelper.CreateAuditEvent((IAuditDbContext)auditEventEf.EntityFrameworkEvent.GetDbContext());
if (newEfEvent == null)
continue;
newEfEvent.Entries = new List<EventEntry>() { entry };
entry.Changes = new List<EventEntryChange> { change };
auditEventEf.EntityFrameworkEvent = newEfEvent;
result = base.InsertEvent(auditEvent);
}
}
return result;
}
}
Check my answer here https://github.com/thepirat000/Audit.NET/issues/323#issuecomment-673007204
You don't need to call CreateAuditEvent() you should be able to iterate over the Changes list on the original event and call base.InsertEvent() for each change, like this:
public override object InsertEvent(AuditEvent auditEvent)
{
var auditEventEf = auditEvent as AuditEventEntityFramework;
if (auditEventEf == null)
return null;
object result = null;
foreach (var entry in auditEventEf.EntityFrameworkEvent.Entries)
{
if (entry.Changes == null || entry.Changes.Count == 0)
continue;
// Call base.InsertEvent for each change
var originalChanges = entry.Changes;
foreach (var change in originalChanges)
{
entry.Changes = new List<EventEntryChange>() { change };
result = base.InsertEvent(auditEvent);
}
entry.Changes = originalChanges;
}
return result;
}
Notes:
This could impact performance, since it will trigger an insert to the database for each column change.
If you plan to use async calls to DbContext.SaveChangesAsync, you should also implement the InsertEventAsync method on your CustomDataProvider
The Changes property is only available for Updates, so if you also want to audit Inserts and Deletes, you'll need to add the logic to get the column values from the ColumnValues property on the event
I am using ASP.NET Boilerplate template.
I want to update Details table, which contains more than one item. If an item exists, it must update, otherwise a new one must be added and all other entries relating to Master primary key in Details table must be deleted. But it is showing an error:
Cannot insert explicit value for identity column in table
'SemesterDetails' when IDENTITY_INSERT is set to OFF
This is the Master table:
public class StudentDegreeCore : Entity<int>
{
[StringLength(150)]
[Required(ErrorMessage = "Enter Degree College ")]
public string DegreeCollege { get; set; }
[Required()]
public string CollegeID { get; set; }
[StringLength(7, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 7)]
[Required(ErrorMessage = "Enter 10th Pass Year")]
public string CommencementYear { get; set; }
public List<StudentSemesterCore> SemesterDetails { get; set; }
}
This is the Details table, represented by the StudentSemesterCore class:
public class StudentSemesterCore
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(150)]
[Required(ErrorMessage = "Enter Year/Semester")]
public string YearOrSemester { get; set; }
[Required()]
public virtual int StudentDegreeID { get; set; }
[ForeignKey("StudentDegreeID")]
public virtual StudentDegreeCore StudentDegreeCore { get; set; }
[StringLength(4, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)]
[Required(ErrorMessage = "Enter Semester Status")]
public string Status { get; set; }
[DisplayName("% of Marks")]
[RegularExpression(#"\d+(\.\d{1,2})?", ErrorMessage = "Numbers With Two decimal Place Allowed")]
public decimal MarkPercentage { get; set; }
}
This is the Update code:
_studentdegreeRepository.Update(st);
CurrentUnitOfWork.SaveChanges();
It shows an error when SaveChanges is called. Actually, I want to update the details if the same value exists, otherwise add new one and all other data relating to the same StudentDegreeID must be removed.
StudentSemesterCore is not derived from Entity.
You don't need to put Id property in StudentSemesterCore. Remove it.
Add StudentDegreeCoreId to StudentSemesterCore as foreign key reference.
I tried this
public override async Task<StudentDegreeDto> Create(StudentDegreeCreateDto input)
{
//CheckCreatePermission();
StudentDegreeCore st = new StudentDegreeCore();
try
{
StudentDegreeCore core = new StudentDegreeCore()
{
Id = input.Id,
Address1 = input.Address1,
Address2 = input.Address2,
City = input.City,
CollegeID = input.CollegeID,
CommencementYear = input.CommencementYear,
CompletionYear = input.CompletionYear,
CurrentYear = input.CurrentYear,
DegreeCollege = input.DegreeCollege,
DegreeId = input.DegreeId,
OverallPercent = input.OverallPercent,
PinCode = input.PinCode,
PostBox = input.PostBox,
State = input.State,
StreamId = input.StreamId,
UserId = input.UserId
};
core.SemesterDetails = new List<StudentSemesterCore>();
foreach (var items in input.SemesterDetails)
{
core.SemesterDetails.Add(new StudentSemesterCore()
{
GPA = items.GPA,
MarkPercentage = items.MarkPercentage,
Status = items.Status,
UserId = items.UserId ,
Id = items.Id,
StudentDegreeID = items.StudentDegreeID ,
YearOrSemester = items.YearOrSemester,
LastModificationTime = DateTime.Now,
CreationTime = DateTime.Now
});
}
var student = core; //ObjectMapper.Map<StudentDegreeCore>(input);
long uid = (AbpSession.UserId == null) ? 0 : Convert.ToInt64(AbpSession.UserId);
st = _studentRepository.Get(student.Id);
if (st != null && st.Id > 0)
{
st.DegreeCollege = student.DegreeCollege;
st.CollegeID = student.CollegeID;
st.CommencementYear = student.CommencementYear;
st.CompletionYear = student.CompletionYear;
st.LastModificationId = Convert.ToInt32(AbpSession.UserId);
st.LastModificationTime = DateTime.Now;
st.StreamId = student.StreamId;
st.DegreeId = student.DegreeId;
st.CurrentYear = student.CurrentYear;
st.OverallPercent = student.OverallPercent;
st.PinCode = student.PinCode;
st.PostBox = student.PostBox;
st.State = student.State;
st.Address1 = student.Address1;
st.Address2 = student.Address2;
st.City = student.City;
st.SemesterDetails = new List<StudentSemesterCore>();
//st.SemesterDetails = student.SemesterDetails;
_studentRepository.Update(st);
foreach (var items in student.SemesterDetails)
{
_studentSemesterRepository.InsertOrUpdate(items);
}
//_studentRepository.Update(st);
CurrentUnitOfWork.SaveChanges();
}
else
{
student.UserId = Convert.ToInt32(AbpSession.UserId);
student.CreationId = Convert.ToInt32(AbpSession.UserId);
_studentRepository.Insert(student);
CurrentUnitOfWork.SaveChanges();
}
}
catch (Exception ex)
{
}
StudentDegreeDto studentDegreeDto = new StudentDegreeDto()
{
Id = input.Id,
Address1 = input.Address1,
Address2 = input.Address2,
City = input.City,
CollegeID = input.CollegeID,
CommencementYear = input.CommencementYear,
CompletionYear = input.CompletionYear,
CurrentYear = input.CurrentYear,
DegreeCollege = input.DegreeCollege,
DegreeId = input.DegreeId,
OverallPercent = input.OverallPercent,
PinCode = input.PinCode,
PostBox = input.PostBox,
State = input.State,
StreamId = input.StreamId,
UserId = input.UserId
};
studentDegreeDto.SemesterDetails = new List<StudentSemesterDto>();
foreach (var items in input.SemesterDetails)
{
studentDegreeDto.SemesterDetails.Add(new StudentSemesterDto()
{
GPA = items.GPA,
MarkPercentage = items.MarkPercentage,
Status = items.Status,
YearOrSemester = items.YearOrSemester,
LastModificationTime = DateTime.Now,
CreationTime = DateTime.Now
});
}
return studentDegreeDto;
}
I got this message when debugged in catch (Exception e). When User fill in all the information, Address and Payment View will get the SalesOrderID and redirect to Complete View. But it didn't show the Complete when it done.
[HttpPost]
public ActionResult AddressAndPayment(SalesOrderHeader order,Customer customer, Address address ,FormCollection values)
{
ViewBag.PersonType = new SelectList(new[] { "EM", "SC", "VC", "IN" } // work
.Select(x => new { value = x, text = x }),
"value", "text");
try
{
if (string.Equals(values["PromoCode"], PromoCode, StringComparison.OrdinalIgnoreCase) == false)
{
return View(order);
}
else
{
order.AccountNumber = User.Identity.Name;
order.OrderDate = DateTime.Now;
address.ModifiedDate = DateTime.Now; // maybe this error
order.Address.PostalCode = "12345";
//Save Order
BikeDBs.SalesOrderHeaders.Add(order);
try
{
BikeDBs.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var entityValidationErrors in e.EntityValidationErrors)
{
foreach (var validationError in entityValidationErrors.ValidationErrors)
{
Console.WriteLine("Properties: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
//Process Order
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
//cart.CreateOrder(order1);
return RedirectToAction("Complete", new { id = order.SalesOrderID });
}
}
catch (Exception exception)
{
//Invalid - redisplay with errors
return View(order);
}
All I want is when the Order is saved, it will redirect to Complete. But in this case, it's not. And here is Address model:
public partial class Address
{
public Address()
{
this.SalesOrderHeaders = new HashSet<SalesOrderHeader>();
this.SalesOrderHeaders1 = new HashSet<SalesOrderHeader>();
}
public int AddressID { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public int StateProvinceID { get; set; }
public string PostalCode { get; set; }
public System.Guid rowguid { get; set; }
[Required()]
public Nullable<System.DateTime> ModifiedDate { get; set; }
public virtual StateProvince StateProvince { get; set; }
public virtual ICollection<SalesOrderHeader> SalesOrderHeaders { get; set; }
public virtual ICollection<SalesOrderHeader> SalesOrderHeaders1 { get; set; }
}
What's a solution and how to fix it?
You can do this pretty easily by using the ModelState, it should catch it. If it doesn't I added code into your catch block to catch it and display the page again with the errors using ModelState.AddModelError.
[HttpPost]
public ActionResult AddressAndPayment(SalesOrderHeader order,Customer customer, Address address ,FormCollection values)
{
ViewBag.PersonType = new SelectList(new[] { "EM", "SC", "VC", "IN" } // work
.Select(x => new { value = x, text = x }),
"value", "text");
if(ModelState.IsValid)
{
try
{
if (string.Equals(values["PromoCode"], PromoCode, StringComparison.OrdinalIgnoreCase) == false)
{
return View(order);
}
else
{
order.AccountNumber = User.Identity.Name;
order.OrderDate = DateTime.Now;
order.Address.PostalCode = values["PostalCode"];
//Save Order
BikeDBs.SalesOrderHeaders.Add(order);
try
{
BikeDBs.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var entityValidationErrors in e.EntityValidationErrors)
{
foreach (var validationError in entityValidationErrors.ValidationErrors)
{
// If this far add errors to model errors and show view again.
ModelState.AddModelError(validationError.PropertyName, validationError.ErrorMessage);
Console.WriteLine("Properties: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
return View(order);
}
//Process Order
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(order);
//cart.CreateOrder(order1);
return RedirectToAction("Complete", new { id = order.SalesOrderID });
}
}
catch (Exception exception)
{
//Invalid - redisplay with errors
return View(order);
}
}
return View(order);
}
For my answer I assume that the properties PostalCode and PersonType are of type string and are defined as not nullable.
I think the error messages you get clearly say what the problem is. The properties PostalCode and PersonType are required, that means they need to have a value other than null.
So when you do not set the properties to a value other than null and you try to save your entity you will get the error messages.
To fix it you will net to set the properties to some values (maybe a default value) or you have to change your EntityModel to specify that these properties are nullable
In debugging the issue in this thread: InvalidCastException when querying nested collection with LINQ I found out that something is wrong with how my Category EntitySet is populated. After selecteding a Category and throwing this exception to see what's going on I get this:
throw new Exception("CID: " + cat.CategoryID +
" LCID: " + cat.LocalizedCategories.First().LocalizedCategoryID +
" CID from LC: " + cat.LocalizedCategories.First().Category.CategoryID);
CID: 352 LCID: 352 CID from LC: 191
What am I doing wrong that causes CategoryID to have different values depending on how I LINQ to it? It should be 191, and not the same value as the LocalizedCategoryID.
This is the code I use to get the Category:
int categoryId = 352; // In reality this comes from a parameter and is supposed
// to be 191 to get the Category.
var cat = categoriesRepository.Categories.First(c => c.CategoryID == categoryId);
This is my domain object with some unrelated stuff stripped:
[Table(Name = "products")]
public class Product
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter a product name")]
[Column]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a description")]
[DataType(DataType.MultilineText)]
[Column(Name = "info")]
public string Description { get; set; }
private EntitySet<Category> _Categories = new EntitySet<Category>();
[System.Data.Linq.Mapping.Association(Storage = "_Categories", OtherKey = "CategoryID")]
public ICollection<Category> Categories
{
get { return _Categories; }
set { _Categories.Assign(value); }
}
}
[Table(Name = "products_types")]
public class Category
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int CategoryID { get; set; }
public string NameByCountryId(int countryId)
{
return _LocalizedCategories.Single(lc => lc.CountryID == countryId).Name;
}
private EntitySet<LocalizedCategory> _LocalizedCategories = new EntitySet<LocalizedCategory>();
[System.Data.Linq.Mapping.Association(Storage = "_LocalizedCategories", OtherKey = "LocalizedCategoryID")]
public ICollection<LocalizedCategory> LocalizedCategories
{
get { return _LocalizedCategories; }
set { _LocalizedCategories.Assign(value); }
}
private EntitySet<Product> _Products = new EntitySet<Product>();
[System.Data.Linq.Mapping.Association(Storage = "_Products", OtherKey = "ProductID")]
public ICollection<Product> Products
{
get { return _Products; }
set { _Products.Assign(value); }
}
}
[Table(Name = "products_types_localized")]
public class LocalizedCategory
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int LocalizedCategoryID { get; set; }
[Column(Name = "products_types_id")]
private int CategoryID;
private EntityRef<Category> _Category = new EntityRef<Category>();
[System.Data.Linq.Mapping.Association(Storage = "_Category", ThisKey = "CategoryID")]
public Category Category
{
get { return _Category.Entity; }
set { _Category.Entity = value; }
}
[Column(Name = "country_id")]
public int CountryID { get; set; }
[Column]
public string Name { get; set; }
}
This (in class Category) looks weird:
[System.Data.Linq.Mapping.Association(Storage = "_LocalizedCategories",
OtherKey = "LocalizedCategoryID" )] // ????
public ICollection<LocalizedCategory> LocalizedCategories
Category has a collection of LocalizedCategorys, which means that in the database the table products_types_localized has a foreign keyCategoryID. That field should be the "OtherKey". How was this mapping generated?