I have an array of objects.
I want to copy this array of objects into another array, except one property of the first array which is an identity column. How do I do that ?
public class Lot
{
[Key]
public int LotNumber { get; set; }
public string LotName { get; set; }
}
Lot[] ExistingLots = (from l in _context.Lot.Where(c => c.NumLot == 999).Select l).ToArray();
int size = ExistingLots.Length;
Compteur[] DestinationLots = new Compteur[size];
//Copy all but the LotNumber
Array.Copy(ExistingLots , 1, DestinationLots , 1, CompteursExistants.Length-size);
Create new Lot objects using your existing values, then add these back into your DbSet:
Lot[] destinationLots = ExistingLots
.Select(el => new Lot { LotName = el.LotName })
.ToArray();
_context.Lot.Add(destinationLots);
_context.SaveChanges();
I decorate the LotNumber with Identity and it now works. I had removed it because of a data import where the column values needed to be kept.
Thanks all !
public class Lot
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int LotNumber { get; set; }
public string LotName { get; set; }
}
Related
Consider an Sqlite database, whose partial schema is shown below (we are not considering the Book_Tag table here). Note the many-to-many relationship between media items and tags using the link table Media_Tag:
An object model for these tables is as follows:
public enum MediaType
{
Dvd,
BluRay,
Cd,
Vhs,
Vinyl,
Other
}
public class MediaItem
{
public MediaType type { get; set; }
public long number { get; set; }
public int runningTime { get; set; }
public int releaseYear { get; set; }
public ICollection<Tag> tags { get; set; }
}
public class Tag
{
public string name { get; set; }
}
currently, Dapper is being used to read from the Media table, but without considering tags. The code is as follows:
public IEnumerable<MediaItem> readAll()
{
using (var db = new SqliteConnection(this.connectionString))
{
db.Open();
var sql = "SELECT * FROM Media;";
return db.Query<MediaItem>(sql);
}
}
public MediaItem readById(int id)
{
using (var db = new SqliteConnection(this.connectionString))
{
db.Open();
var sql = "SELECT * FROM Media WHERE id = #id;";
var #params = new { id = id };
return db.Query<MediaItem>(sql, #params).First();
}
}
How to change this so that the tag property of MediaItem is considered when creating the objects, for both cases (read by id and read all rows from the table)? Is a join query required? I'm sure Dapper has a way of doing this nicely, but I don't know how it's done.
You are not interested in anything from the link table so something like this SQL should do:
SELECT M.Id, M.title, M.type, M.Number, M.image, M.runningTime, M.releaseYear, T.Id, T.Name FROM Media as M
INNER JOIN Media_Tag AS MT ON M.id = MT.mediaId
INNER JOIN Tags AS T ON T.id = MT.tagId
If SqLite allows you can use M.*, T.* instead.
I have taken the liberty to add Id properties to your entity classes. I think you are going to need it, otherwise all your tags will be different instead of being unique. You might make it work without it, but it should make your life easier.
public class MediaItem
{
public int Id { get; set; } // New
public MediaType type { get; set; }
public long number { get; set; }
public int runningTime { get; set; }
public int releaseYear { get; set; }
public ICollection<Tag> tags { get; set; }
}
public class Tag
{
public int Id { get; set; } // New
public string name { get; set; }
}
Since both your entity classes have a unique id, you will have to pick them up and make sure they are unique going through the results. We do that by using dictionaries to keep them. I'm only showing the ReadAll, you should be able to do ReadById accordingly.
string sql = "<see above>";
using (var db = new SqliteConnection(this.connectionString))
{
var mediaDictionary = new Dictionary<int, Media>();
var tagDictionary = new Dictionary<int, Tag>();
var list = db.Query<Media, Tag, Media>(
sql,
(media, tag) =>
{
Media mediaEntry;
if (!mediaDictionary.TryGetValue(media.Id, out mediaEntry))
{
// Haven't seen that one before, let's add it to the dictionary
mediaEntry = media;
mediaDictionary.Add(mediaEntry.Id, mediaEntry);
}
Tag tagEntry;
if (!tagDictionary.TryGetValue(tag.Id, out tagEntry))
{
// Haven't seen that one before, let's add it to the dictionary
tagEntry = tag;
tagDictionary.Add(tagEntry.Id, tagEntry);
}
// Add the tag to the collection
mediaEntry.Tags.Add(tagEntry);
return mediaEntry;
},
splitOn: "Id") // This default and could be omitted
.Distinct()
.ToList();
Not sure if i worded the question correctly, but what im trying to do is return a new viewmodel with one of the parts being a booking:
public class Booking
{
public int BookingId { get; set; }
public int CustomerId { get; set; }
public Guid UniqueId { get; set; }
public string EventId { get; set; }
public bool IsPaid { get; set; }
public double Price { get; set; }
public DateTime BookingDate { get; set; }
public DateTime DateBooked { get; set; }
[JsonIgnore]
public Customer Customer { get; set; }
[JsonIgnore]
public ICollection<BookingService> BookingServices { get; set; }
[NotMapped]
public IEnumerable<Service> Services { get; set; }
}
and my query is:
var customers = _dbContext.Customers
.Select(c => new CustomerBookingsViewModel
{
Customer = c,
Bookings = c.Bookings.Select(b => new Booking
{
BookingId = b.BookingId,
BookingDate = b.BookingDate,
DateBooked = b.DateBooked,
CustomerId = b.CustomerId,
UniqueId = b.UniqueId,
EventId = b.EventId,
IsPaid = b.IsPaid,
Price = b.Price,
Services = b.BookingServices.Select(s => s.Service)
}),
}
)
.ToList();
What I want to know is how to I select all the booking info into the booking without selecting each part, ie:
BookingId = b.BookingId,
BookingDate = b.BookingDate,
DateBooked = b.DateBooked,
CustomerId = b.CustomerId,
UniqueId = b.UniqueId,
EventId = b.EventId,
IsPaid = b.IsPaid,
Price = b.Price,
Can it be done or because the list of services is inside the booking model it cant?
Thanks.
You could implement the IClonable interface on your class.
public class MyClass : ICloneable
{
public int Id { get; set; }
public object Clone() => MemberwiseClone();
}
Usage:
var list1 = new List<MyClass>
{
new MyClass() { Id = 2 },
new MyClass() { Id = 5 }
};
var list2 = list1.Select(x => (MyClass)x.Clone()).ToList();
list2.First().Id = 10; //list1 won't be affected
You should use AutoMapper here to avoid writing each path.
https://automapper.org/
http://docs.automapper.org/en/stable/Getting-started.html
There is no other way, at least it is not related to LINQ or queries.
The question "How to clone an object" has been answered here:
Creating a copy of an object in C#
There is no LINQ way to do this. I would suggest using custom Attribute marking every property you want to copy. This would help if you want not to copy the whole object but some properties. After marking every property you need you can just set the marked props with reflection from one of the objects to the other.
I need the possiblity to create Code in C# like this
public class SummaryA
{
public string name { get; set; }
public string surename { get: set; }
public int age { get; set;}
}
now I create an list object from the class SummaryA
List<SummaryA> list1= new List<SummaryA>();
yet I need the possibility to remove the column age from the list Summary, anyone have ideas?
I need this for some more columns, so I wish the list was dynamically or some things else.
sry for my bad english.
To completely remove the column you really need another class to store the data in, for example:
public class AgelessSummaryA
{
public string name { get; set; }
public string surename { get: set; }
}
And now you can project the first list into a new list of this class with Linq and Select:
List<AgelessSummaryA> agelessSummaries = ageSummaries
.Select(s => new AgelessSummaryA
{
name = s.name,
surename = s.surename
})
.ToList();
To use it for in a grid or for some display i guess, then you can use anonymous types where you can shape the data the way you like:
var projectedList = (from l in list1
select new
{
name = l.name,
surename = l.surename
}).ToList();
I have two models:
public class HouseType
{
public int Id { get; set; }
public string TypeName { get; set; }
public virtual IEnumerable<HouseModel> HouseModels { get; set; }
}
and
public class HouseModel
{
public int Id { get; set; }
public string ModelName { get; set; }
[DisplayFormat(DataFormatString = "{0:n2}")]
public double StandardPrice { get; set; }
[ForeignKey("HouseType")]
public int HouseTypeID { get; set; }
public virtual HouseType HouseType { get; set; }
public virtual IEnumerable<HouseUnit> HouseUnits { get; set; }
}
I am returning a JSON result, so as expected I cannot manipulate it in a view, because the display is handled by a javascript file that I made.
I am trying to retrieve the number of HouseModel that is contained by HouseType. I have tried:
db.HouseTypes.Select(h => new
{
HouseCount = h.HouseModels.Count()
}).ToList();
But Entity Framework complains about it. How can I access the count of related records inside an entity? Any help will be much appreciated. Thanks.
Use
public virtual ICollection<HouseUnit> HouseUnits { get; set; }
instead of
public virtual IEnumerable<HouseUnit> HouseUnits { get; set; }
Hope this helps.
Simply speaking, the trouble is that EF is trying to execute the .Select() statement on the db server but, of course, the db server does not know how to create a new object.
You first need to bring back the counts then create your objects so something like this should work better:
var listOfCounts = db.HouseTypes
.Select(h => h.HouseModels.Count())
.ToList()
.Select(c => new
{
HouseCount = c
})
.ToList();
in this example when the first .ToList() is executed the db needs only return a set of numbers (the counts of HouseModels in each HouseType) then we have a List<int> in local memory from which we can create our objects with the second Select statement.
As an aside...
It wasn't part of your original question but maybe you'd want to consider a dictionary rather than a list so you have some means of identifying which count of HouseModels belonged to each HouseType? in which case we could do something like:
Dictionary<int,string> houseModelCounts = db.HouseTypes
.ToDictionary(h => h.Id, h => h.HouseModels.Count());
which would give a dictionary keyed with the HouseType Id with values for the count of HouseModels in each type. I don't know your context though so maybe unnecessary for you?
I am working on an application for Windows Phone platform. Run into a question.
I'd 2 different List, 1 is direct read from xml file, and the other by some calculation. And I want to merge this two lists into 1, so I can display it out.
List 1:
public class studentClass1
{
public string studentID { get; set; }
public string studentFirstName { get; set; }
public string studentLastName { get; set; }
}
List 2:
public class studentClass2
{
public string studentID { get; set; }
public string studentGradePoint { get; set; }
}
First of all, I had readout the studentClass1 via
var studentList= from query in studentIndex.Descendants("student")
select new driversClass
StudentList1 = studentList.ToList();
Secondly, I process the student Grade Point calculation on the function and output to the 2nd list :
studentClass2 SG = new studentClass2
{
studentID = thestudentID ,
studentGradePoint = thestudentGradePoint .ToString()
};
StudentList2.Add(SG);
studentListAll = StudentList1 + StudentList2
now, I want to join this two list together so that I can output to screen by calling
studentResultListBox.Itemsource = StudentListAll;
any suggestion the code how would look like?
Thanks.
Assuming you just want to combine the appropriate info from both lists (it is not totally clear from your question) - introduce a third class studentClass3 that holds all the properties you want and use a join to match instances with a matching studentID:
var studentList3 = (from s1 in studentList1
join s2 in studentList2 on s1.studentID equals s2.studentID
select new studentClass3()
{
studentFirstName = s1.studentFirstName,
studentID = s1.studentID,
studentGradePoint = s2.studentGradePoint,
studentLastName = s1.studentLastName
}).ToList();
In general this problem should be rather solved when you read in the XML than trying to combine the lists later on - having three different classes for students might be confusing. Also take a look at the recommended naming conventions, they are a little off.
Use interface, e.g.
interface IStudent
{
string studentID { get; }
// other common properties below
}
public class StudentClass1 : IStudent
{
public string studentID { get; set; }
public string studentFirstName { get; set; }
public string studentLastName { get; set; }
}
public class StudentClass2 : IStudent
{
public string studentID { get; set; }
public string studentGradePoint { get; set; }
}
and then
studentResultListBox.Itemsource = list1.Cast<IStudent>()
.Concat(list2.Cast<IStudent>())
.ToList();
Or, if the inheritance is not the case, just cast everything to System.Object (+ override object.ToString)
studentResultListBox.Itemsource = list1.Cast<object>()
.Concat(list2.Cast<object>())
.ToList();