Entity Framework save collection - c#

I have Entity Framework Code First models. When I try save collection of Accounts in one insert i get error message.
public class User
{
[Key]
public int Usr_Id { get; set; }
[Required]
[MaxLength(35)]
public string Name { get; set; }
[Required]
[MaxLength(35)]
public string Surname { get; set; }
[Required]
[MaxLength(35)]
public string Location { get; set; }
//NAVIGATION
public User()
{
UserDevices = new List<UserDevice>();
}
public virtual ICollection<UserDevice> UserDevices { get; set; }
}
public class UserDevice
{
[Key]
public int UsrDev_Id { get; set; }
[Required]
[MaxLength(50)]
public string PurposeOfUse { get; set; }
// NAVIGATION
public UserDevice()
{
Accounts = new List<Account>();
}
//User can have many UserDevice
public int Usr_Id { get; set; }
public virtual User User { get; set; }
//UserDevice can have many Acoount
public virtual ICollection<Account> Accounts { get; set; }
//One to one
public virtual SoftwareInformation SoftwareInformation { get; set; }
public virtual HardwareInformation HardwareInformation { get; set; }
}
public class Account
{
[Key]
public int Acc_Id { get; set; }
public string Name { get; set; }
//NAVIGATION
//UserDevice can have many Account
public int UsrDev_Id { get; set; }
public virtual UserDevice UserDevice { get; set; }
}
Insert of new UserDevice
List<Account> accountsList = new List<Account>();
foreach (var item in model.DeviceInformations.OS.Accounts)
{
accountsList.Add(new Account { Name = item.Name });
}
_unitOfWork.UserDevices.Add(new UserDevice
{
Usr_Id = model.Usr_Id,
PurposeOfUse = model.PurposeOfUse,
HardwareInformation = new HardwareInformation
{
MB_Manufacturer = model.DeviceInformations.Motherboard.Manufacturer,
MB_Model = model.DeviceInformations.Motherboard.Model,
MB_Name = model.DeviceInformations.Motherboard.Name,
MB_UUID = model.DeviceInformations.Motherboard.UUID,
CPU_Manufacturer = model.DeviceInformations.Processor.Manufacturer,
CPU_MaxClockSpeed = model.DeviceInformations.Processor.MaxClockSpeed,
CPU_Name = model.DeviceInformations.Processor.Name,
},
SoftwareInformation = new SoftwareInformation
{
OS_Edition = model.DeviceInformations.OS.Edition,
OS_HostName = model.DeviceInformations.OS.HostName,
OS_Language = model.DeviceInformations.OS.Language,
OS_Platform = model.DeviceInformations.OS.Platform,
OS_ProductKey = model.DeviceInformations.OS.ProductKey,
OS_ServicePackVersion = model.DeviceInformations.OS.ServicePackVersion,
OS_Version = model.DeviceInformations.OS.Version
},
Accounts = accountsList
});
_unitOfWork.Commit();
Error message
{"Cannot insert the value NULL into column 'Acc_Id', table 'LICENSE_WATCHER_TEST.dbo.Accounts'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
It happends when I try save Accout collection. Is there a way how to save Accouts collection in one Insert?

Acc_id is null on insert. I would expect that ID to be auto generated in cases like this. Is it possible that you have the Acc_id column on the Account Table set up as PK, but not an Identity column in the database?
That might cause the behavior that you are experiencing.

Well, you have Acc_Id defined as Primay key and it seems you are trying to insert a null value to table.
Here you create account list, but you only fill in Name
foreach (var item in model.DeviceInformations.OS.Accounts)
{
accountsList.Add(new Account { Name = item.Name });
}
And then you don't do any changes in accountsList
Before commit you do Accounts = accountsList which doesn't have Id filled in and you try to commit.
Try something like this:
foreach (var item in model.DeviceInformations.OS.Accounts)
{
accountsList.Add(new Account { Acc_Id = !!someIdHere!!, Name = item.Name });
}

Related

.NET Foreign Key Cannot be Inserted

I have used foreign keys many times before and set up these models just the same however I'm getting this error, the error also occurs when writing usertableID:
A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = FK_dbo.Outreaches_dbo.OutreachNames_OutreachNamesID ]
Can anyone explain?
Code causing error:
foreach (var item in records)
{
List<string> foundEmails = EmailScraper.Main(item.domain);
string[] emails = foundEmails.ToArray();
var outreach = new Outreach {
domain = item.domain,
email1 = foundEmails.ElementAtOrDefault(0),
email2 = foundEmails.ElementAtOrDefault(1),
email3 = foundEmails.ElementAtOrDefault(2),
email4 = foundEmails.ElementAtOrDefault(3),
email5 = foundEmails.ElementAtOrDefault(4),
email6 = foundEmails.ElementAtOrDefault(5),
UserTableID = UserTableID,
OutreachNamesID = listNumber
};
db.OutreachLists.Add(outreach);
db.SaveChanges();
}
var outreachlist = new OutreachNames
{
ID = listNumber,
listName = model.listName,
listCount = count,
listSent = 0,
unread = 0,
replyRate = 0,
UserTableID = UserTableID,
};
db.OutreachNames.Add(outreachlist);
db.SaveChanges();
Model Outreach:
namespace Linkofy.Models
{
public class Outreach
{
public int ID { get; set; }
public int? OutreachNamesID { get; set; }
public virtual OutreachNames OutreachNames { get; set; }
public string name { get; set; }
[Required]
public string domain { get; set; }
public string email1 { get; set; }
public string email2 { get; set; }
public string email3 { get; set; }
public string email4 { get; set; }
public string email5 { get; set; }
public string email6 { get; set; }
public string email7 { get; set; }
public string email8 { get; set; }
public int? UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
}
}
Model OutreachNames:
namespace Linkofy.Models
{
public class OutreachNames
{
public int ID { get; set; }
[Required]
public string listName { get; set; }
public int listCount { get; set; }
public int listSent { get; set; }
public int unread { get; set; }
public int replyRate { get; set; }
public virtual ICollection<Outreach> OutreachLists { get; set; }
public int? UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
}
}
When saving your Outreach you are setting the FK OutreachNamesID to an ID of a record which doesn't exist yet. You need to create this record first or use Entity Framework to create OutreachNames as a child entity. Both entities need to be persisted to the db in one transaction.
You can create the child entity inside of the parent and persist them in one go like this:
var outreach = new Outreach
{
OutreachNames = new OutreachNames
{
...
}
}
db.OutreachLists.Add(outreach);
db.SaveChanges();

Retrieving value from combobox Winforms / Entity Framework

I am trying to populate my combobox with a list of companies and then get value of selected company (its Id) into my database.
I have this class CBItem:
public class CBItem
{
public string Name { get; set; }
public int Value { get; set; }
public override string ToString()
{
return Name;
}
}
I add items to combobox using this:
using (var db = new DataContext())
{
var list_of_companies = db.Companies;
foreach (Company c in list_of_companies)
{
CBItem item = new CBItem();
item.Name = c.Name;
item.Value = c.Id;
comboBox1.Items.Add(item);
}
}
Problem is when I want to get value of selected item, I have tried something like this:
new_person.Company.Id = (comboBox1.SelectedItem).Value;
Of course it doesn't work :/ Any tips?
You are right, there is something wrong with this line:
new_person.Company.Id
I don't know what is wrong. I have model Person which has foreign key to company's id.
Maybe there si something wrong with my DB model.
My Person model:
public class Person
{
public Person()
{
}
public int PersonId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Job { get; set; }
public int Phone { get; set; }
public int Mobile { get; set; }
public Company Company { get; set; }
}
Company model:
public class Company
{
public Company()
{
}
public int Id { get; set; }
public string Name { get; set; }
public int NIP { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int Code { get; set; }
public int Phone { get; set; }
public string Notes { get; set; }
public ICollection<Person> Person { get; set; }
}
Saving code:
using (var db = new DataContext())
{
Person new_person = new Person();
new_person.Name = textBox1.Text;
new_person.Surname = textBox2.Text;
new_person.Job = textBox3.Text;
new_person.Phone = Int32.Parse(textBox4.Text);
new_person.Mobile = Int32.Parse(textBox5.Text);
new_person.Company.Id = (comboBox1.SelectedItem as CBItem).Value;
db.Person.Add(new_person);
db.SaveChanges();
MessageBox.Show("Person successfully added!");
this.Close();
}
Your code works fine if:
new_person is not null
new_person.Company is not null
combobox.SelectedItem is not null
Also you have to cast combobox.SelectedItem to CBItem like this:
new_person.Company.Id = ((CBItem)comboBox1.SelectedItem).Value;
As a site note instead of adding each item one by one you can archive the same thing by binding the ComboBox via its DataSource property to an object that implements the IList interface or an Array:
comboBox1.DataSource = list_of_companies
.Select(c => new CBItem {
Name = c.Name,
Value = c.Id
})
.ToArray();

How to Join In LiteDb

How can i join between two table in LiteDb Like SQL
Example : I Have Two table User and ActivityLog
Here is the Model
public class ActivityLog
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string Action { get; set; }
public DateTime ActionDateTime { get; set; }
}
public class User
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public DateTime LoginDate { get; set; }
}
I need to join Activity.UserID = User.UserId.
Is there any way to join like sql
From official documentation
LiteDB is a document database, so there is no JOIN between
collections. If you need reference a document in another document you
can use DbRef. This document reference can be loaded when the
database is initialized or when a query is run, or after a query is
finished.
In your case, you can do smth like
public class ActivityLog
{
[BsonId]
public int Id { get; set; }
public DbRef<User> User { get; set; }
public string Action { get; set; }
public DateTime ActionDateTime { get; set; }
}
public class User
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public DateTime LoginDate { get; set; }
}
//usage
// Getting user and activityLog collections
var usersCollection = db.GetCollection<User>("Users");
var activityLogsCollection = db.GetCollection<ActivityLog>("ActivityLogs");
// Creating a new User instance
var user = new User { UserId = 5, ...};
usersCollection.Insert(user);
// Create a instance of ActivityLog and reference to User John
var activityLog = new ActivityLog
{
OrderNumber = 1,
OrderDate = DateTime.Now,
//Add it by DbRef
User = new DbRef<User>(usersCollection, user.UserId)
};
activityLogsCollection.Insert(activityLog)
See the documentation for more details.

Foreign key value not populating automatically

I've created a foreign key reference to the 'ApplicationUser' entity in my 'YogaSpace' entity seen below, but when I create a new YogaSpace and save it to the DB the column 'ApplicationUserRefId' is null? Shouldn't it contain the user id from application user without me inserting it into the entity before I save it? I know the answer would seem to be yes because I have another member in 'YogaSpace' called Images and it gets the 'YogaSpace' entity id automatically without me inserting it into the 'Images' entity before I save. So I don't have to insert the id there. How come it doesn't insert the user id with 'YogaSpace'?
public class YogaSpace
{
public int YogaSpaceId { get; set; }
public virtual ICollection<YogaSpaceImage> Images { get; set; }
[MaxLength(128)]
public string ApplicationUserRefId { get; set; }
[ForeignKey("ApplicationUserRefId")]
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public DateTime MembershipCreated { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? Birthdate { get; set; }
public Gender Gender { get; set; }
public virtual ICollection<YogaSpace> YogaSpaces { get; set; }
}
public class YogaSpaceImage
{
public int YogaSpaceImageId { get; set; }
public byte[] Image { get; set; }
public byte[] ImageThumbnail { get; set; }
public string ContentType { get; set; }
public int Ordering { get; set; }
[Index]
public int YogaSpaceRefId { get; set; }
[ForeignKey("YogaSpaceRefId")]
public virtual YogaSpace YogaSpace { get; set; }
}
Here is how I create a 'YogaSpace' entity. You can see I don't put anything into 'ApplicationUserRefId', BUT I expect it to autopopulate with user id from Application User, just like YogaSpacerefId gets auto populated when I create an image and save it.
var newSpace = new YogaSpace
{
Overview = new YogaSpaceOverview
{
Title = viewModel.Title,
Completed = ListingComplete.Incomplete
},
Listing = new YogaSpaceListing
{
Accommodation = (YogaSpaceAccommodation)viewModel.YogaSpaceAccommodation,
SpaceLocation = (YogaSpaceLocation)viewModel.YogaSpaceLocation,
SpaceType = (YogaSpaceType)viewModel.YogaSpaceType
},
Details = new YogaSpaceDetails
{
Completed = ListingComplete.Complete
},
Address = new YogaSpaceAddress
{
Completed = ListingComplete.Incomplete
},
DateCreated = DateTime.Now
};
yogaSpaceRepository.InsertOrUpdate(newSpace);
yogaSpaceRepository.Save();

EF inserting object to DB getting validation error

I am trying insert into database my model with relation one to many:
I have two models:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public virtual Country Country { get; set; }
}
public class Country
{
public int Id { get; set; }
public string CountryName { get; set; }
public virtual ICollection<User> Users { get; set; }
}
User user = new User()
{
Name = model.Name,
Surname = model.Surname,
Country = new Country { Id = 1 }
};
When I try to insert it to the database I get exception
Validation failed for one or more entities.
The CountryName field is required (CoutryName column is required in database)
I don't want each time call to database to get full Country object, any ideas?
Instead of instancing a new country, do something like this:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int CountryId { get; set; }
[ForeignKey("CountryId")]
public virtual Country Country { get; set; }
}
public class Country
{
public int Id { get; set; }
public string CountryName { get; set; }
public virtual ICollection<User> Users { get; set; }
}
User user = new User()
{
Name = model.Name,
Surname = model.Surname,
CountryId = 1;
};
This explicitly sets the CountryID on the User.
You should use "FK Associations" instead "Independent Associations" this is create article about it:
http://blogs.msdn.com/b/efdesign/archive/2009/03/16/foreign-keys-in-the-entity-framework.aspx

Categories