Error: c# member names cannot be the same as their enclosing type - xmlserializer

this is XML
<TEST ID=1 TITLE="HELLO" TEST=false/>
this file is XmlSerializer
[Serializable]
[XxmlRoot(ElementName = "TEST"]
public class TEST
{
[XmlAttribute(AttributeName = "ID"]
public int ID {get;set;}
[XmlAttribute(AttributeName = "TITLE"]
public string TITLE {get;set;}
[XmlAttribute(AttributeName = "TEST"]
public bool TEST {get;set;}
}
Run This Project
Error Message
"'TEST' member names cannot be the same as their enclosing type"
I understand it. but I CAN NOT rename this AttributeName and RootName,
XML file is Never Change, Not my File. How can I Change this Serializable File ?

You can rename your member variables while keeping the actual XML tags the same. The AttributeName you have used enables this. You can actually do this:
[Serializable]
[XmlRoot(ElementName = "TEST"]
public class TestTag
{
[XmlAttribute(AttributeName = "ID"]
public int IdAttribute { get; set; }
[XmlAttribute(AttributeName = "TITLE"]
public string TitleAttribute { get; set; }
[XmlAttribute(AttributeName = "TEST"]
public bool TestAttribute { get; set; }
}
or something similar. Your XML file will remain the same!

Related

Mapster - mapping descendant classes from base class

Classes:
public class Department
{
public string Name { get; set; }
}
public class DepartmentA : Department
{
public string NameA { get; set; }
}
public class Employee
{
public string Name { get; set; }
public int Salary { get; set; }
public string Address { get; set; }
public Department Department { get; set; }
}
public class EmployeeDTO
{
public string Name { get; set; }
public int Salary { get; set; }
public string Address { get; set; }
public Department Department { get; set; }
}
Code:
DepartmentA departmentA = new DepartmentA { NameA = "depA", Name = "dep" };
Employee emp = new Employee
{
Name = "James",
Salary = 20000,
Address = "London",
Department = departmentA
};
//Mapster
var empDTO = emp.Adapt<EmployeeDTO>();
//AutoMapper
//var config = new MapperConfiguration(cfg => cfg.CreateMap<Employee, EmployeeDTO>());
//var mapper = config.CreateMapper();
//EmployeeDTO empDTO = mapper.Map<EmployeeDTO>(emp);
Console.WriteLine("SourceType:" + emp.Department.GetType().Name);
Console.WriteLine("DestType:" + empDTO.Department.GetType().Name);
If you run the code you will see that SourceType and DestType are not the same. How do I achieve that they are the same? Mapster mapps department as Department class (ancestor) and not as DepartmentA class (descendant).
In this example I know that there is descendant in emp.Department but in my app I won't know. So the solution of this problem must be generic.
I tried to solve this problem in AutoMapper. Got the same results. As #Prolog wrote below, in AutoMapper is working. I updated main code. I am still interested if someone solved issue in Mapster.
You need to use ShallowCopyForSameType, AutoMapper will perform deep copy only declared types, Mapster perform deep copy for all types.

Map from Typed object to dynamic

I was trying to map from a typed object to dynamic but that seems to be not possible.
For example:
public class Customer
{
public string CustomerName {get; set;}
public Category Category {get; set;}
}
public class Category
{
public string CategoryName {get; set;}
public int IgnoreProp {get; set;}
}
Then I would like my result like below:
var customer = new Customer
{
CustomerName = "Ibrahim",
Category = new Category
{
CategoryName = "Human",
IgnoreProp = 10
}
};
dynamic dynamicCustomer = Mapper.Map<Customer, dynamic>(customer);
Can I configure AutoMapper to somehow handle this ?
Looks like it is possible, the following test succeeds:
public class SourceObject
{
public int IntProperty { get; set; }
public string StringProperty { get; set; }
public SourceObject SourceProperty { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var result = AutoMapper.Mapper.Map<dynamic>(new SourceObject() {IntProperty = 123, StringProperty = "abc", SourceProperty = new SourceObject()});
Console.WriteLine("Int " + result.IntProperty);
Console.WriteLine("String " + result.StringProperty);
Console.WriteLine("Object is " + (result.SourceProperty == null ? "null" : "not null").ToString());
Console.ReadLine();
}
}
This outputs a dynamic object with the mapped properties from the SourceObject
You don't need to use AutoMapper to map to a dynamic object:
dynamic dynamicCustomer = customer;
Console.WriteLine(dynamicCustomer.CustomerName); // "Ibrahim"
Console.WriteLine(dynamicCustomer.Category.CategoryName); // "Human"

The properties expression is not valid. The expression should represent a property

I have these two entities
public class Song : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
[Required]
public virtual Album Album { get; set; }
[Required]
public int TrackNumber { get; set; }
}
public class Album : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
public virtual IEnumerable<Song> Songs { get; set; }
[Required]
public int AlbumNumber { get; set; }
}
Path is defined in the IPathHavingEntity interface.
In my Seed method I want to add a song to the Songs table only if it doesn't exist. For this reason I check that the album path and song path combination don't exist already before adding it thus
context.Songs.AddOrUpdate(
s => new { FilePath = s.Path, AlbumPath = s.Album.Path },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
The problem is I get this error
The properties expression 's => new <>f__AnonymousType0``2(FilePath =
s.Path, AlbumPath = s.Album.Path)' is not valid. The expression should
represent a property: C#: 't => t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }' VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.
What's the problem?
In my case, The Only modification I did that on the Model Classes forget to put {get; set;} with the property declaration, Thus ...It's solved my problem.
Like this:
Before:
public int Supplier_ID;
public String Supplier_Code;
After:
public int Supplier_ID { get; set; }
public String Supplier_Code { get; set; }
Kindly Check your Model Classes should have the Get/Set property
I struggled with a similar issue for several hours today and was finally able to resolve it. I'm not sure if this will work for your situation but it's worth investigating.
The problem may be caused by the Album property of your Song entity being marked as virtual. I'm not an EF expert but I don't think it likes that virtual property when initializing your anonymous type. Add a non-virtual property for the album path (but keep the virtual navigation property), like this:
public class Song : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
[Required]
public virtual Album Album { get; set; }
public string AlbumPath { get; set; }
[Required]
public int TrackNumber { get; set; }
}
And then perform the AddOrUpdate using that non-virtual property, like this:
context.Songs.AddOrUpdate(
s => new { FilePath = s.Path, AlbumPath = s.AlbumPath },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
EF should then only allow you to add songs where the given song path and album path do not already exist. Whether your Song domain object can have a non-virtual AlbumPath property is another question but this should at least allow you to run your seed method in the way you described.
EF does not create a column for a property which does not have either getters or setters. For example, EF will not create columns for the following City and Age properties.
using System.ComponentModel.DataAnnotations;
public class Student
{
private int _age = 0;
public int StudentId { get; set; }
public string StudentName { get; set; }
public string City { get{ return StudentName;} }
public int Age { set{ _age = value;} }
}
Referance : https://www.entityframeworktutorial.net/code-first/notmapped-dataannotations-attribute-in-code-first.aspx
In my case, changing the following values in the mapper worked.
From:
this.HasKey(t => new { FirstName = t.FirstName, LastName = t.LastName });
To:
this.HasKey(t => new { t.FirstName, t.LastName });
What has not been mentioned in any of other answers is that the source of the problem in any case shown is the same: The "custom identification expression" passed in as a parameter of the AddOrUpdate method has to be a valid property of the entity being inserted or updated. Also, it will not accept ComplextType.Property there.
For example:
context.Songs.AddOrUpdate(
s => new { k.Path, k.AlbumPath },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
Note that the problem was resolved when the AlbumPath was used and also note that the anonymous type requires no other fields to be created. Instead, you just need to specify the property names.
It worth mentioning to be careful when using AddOrUpdate as the result can be destructive.

EntityType has no key defined. [Key] is presented

Entity
public class Region
{
[Key]
public int ID;
public string Name;
public string Description;
}
Model
public class RegionModel
{ [Key]
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Errors
System.Data.Edm.EdmEntityType: : EntityType 'Region' has no key
defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet �Regions� is based
on type �Region� that has no keys defined.
Your class fields need to be changed to properties for EF to use the class correctly;
public class Region
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Region
{
[Key]
public int RegionId{get;set;}
public string Name{get;set;}
public string Description{get;set;}
}
public class RegionModel
{ [Key]
public int RegionModelId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
It works if you have it like ClassNameId.You can even remove [Key] attribute now.
Maybe a strange answer to your problem. But be sure that your project compiles first. i got the same errors when i had added the dataanotations without compiling the project.
I think the code is generated with some kind of reflection.

Returning Associated Members via Ria DomainService Invoke Method

I got this DomainService method I'm calling from my SL ViewModel using the Invoke attribute:
[Invoke]
public ServiceModel.Recipy GetRecipyById(int recipyId)
{
return new Recipy
{
RecipyId = 1,
Name = "test",
Description = "desc",
Author = new Author
{
AuthorId = 1,
Name = "Johan"
}
};
}
The code in my ViewModel looks like this:
public RecipyViewModel()
{
context.GetRecipyById(1, RecipyLoadedCallback, null);
}
private void RecipyLoadedCallback(InvokeOperation<Recipy> obj)
{
_name = obj.Value.Name;
_description = obj.Value.Description;
_authorName = obj.Value.Author.Name;
}
The Recipy and Author POCO/ServiceModel classes:
public class Recipy
{
[Key]
public int RecipyId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
[Association("Author", "RecipyId", "AuthorId")]
[Include]
public Author Author { get; set; }
}
public class Author
{
[Key]
public int AuthorId { get; set; }
public string Name { get; set; }
}
Now, the code works fine, except that the associated Author is not transfered over to the client/viewmodel, the Author property of Recipy is null. I thought that using the [Associate] and [Include] attributes would do the trick?
Thanks for any help, I'm trying hard to grok the DomainService/RIA stuff and I'm close to giving up and go "normal" WCF/REST instead :)
As I understand it, [Invoke] doesn't support complex hierarchies at the moment, so I solved it by making sure I had the correct attributes for [Include] and [Association] on the collection, and went back to using a normal RIA query method instead.

Resources