How i can say EF6 not insert NULL value - c#

I set deafaultValue in migration
AlterColumn("Users", "NotNullValue", c => c.String(nullable: false, defaultValue: "Work it!"));
then i try add new object, and SqlProfiler show me query
INSERT [dbo].[WowTable]([NotNullValue],[OnceMoreValue]) VALUES (NULL, 'val')
that throw "cannot insert the value null into column"
is that any way to stop inserting and updating property when it null?
UPD:
Domain class:
public class User
{
public string NotNullValue { get; set; }
public int Id { get; set; }
public string OnceMoreValue { get; set; }
}
Update method:
public Task AddOrUpdate<TEntity>(TEntity entity) where TEntity : class, IEntity
{
_dbContext.Set<TEntity>().AddOrUpdate(x => x.Id, entity);
return _dbContext.SaveChangesAsync();
}
calling:
AddOrUpdate(new User{OnceMoreValue = "val"});

You can either validate the model using [Required] attribute for NotNullValue property:
public class User
{
[Required]
public string NotNullValue { get; set; }
public int Id { get; set; }
public string OnceMoreValue { get; set; }
}
Ref: https://msdn.microsoft.com/en-in/data/gg193959.aspx
Or from what I see in your migration script, you have a default value for this property ("Work It"). So in your User class constructor, you can set NotNullvalue = "Work It" so that this default value will be saved in the case you mentioned:
AddOrUpdate(new User{OnceMoreValue = "val"});

Related

Foreign table foriegn key value always showing null ef core 3.1

eWhy is my Icollection foreign key always blank I have a foreign table called photos which I have created using the Icollection. Im using ef core 3.1.7 and asp.net core 3.1 how does one get the file attachments VesselsId not to be null
Basically one vessel can have many photos but their could also be many vessels.
public class Vessels {
public int Id { get; set; }
[StringLength(400)]
public string Name { get; set; }
public string FlagName { get; set; }
public ICollection<FileAttachments> PhotosAttachments { get; set; }
}
This is the file attachments
public class FileAttachments {
public int Id { get; set; }
public string Title { get; set; }
public string File { set; get; }
}
In where I Wish to display the photos their blank I use the include statement to try and include them in my query.
var vessels = await _context.Vessels.Where(w=>w.Id==id).Include(c=>c.PhotosAttachments).FirstAsync();
But If I look here it will show PhotosAttachments being of null when I look at the field value sure enough its sitting there null.
I think i need to do something here but im not sure as to what
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
}
Edit 2
Basically i have a generic Upload Files method as such which is called via the submit button
[HttpPost]
public async Task<IActionResult> UploadFiles(List<IFormFile> FormFile, int UploadArea, int PoiId, int VesselId) {
FileAttachments attachments = new FileAttachments {
DocumentPath = filePath,
UploadAreaId = UploadArea,
CaseId = resultCaseId,
FullPath = savedFileName,
FileSize = infoFile.Length,
OrignalFileName = fileAttachments.FileName,
FileAttachmentType = fileAttachmentType,
TennantId = await GetCurrentTennantId(),
Extension = infoFile.Extension.Replace(".", "").ToLower(),
UploadedBy = caseOfficer.Id,
CreatedDate = DateTime.Now,
File = uniqueFilename,
ContentType = fileAttachments.ContentType,
isActive = true,
isDeleted = false
};
if (PoiId != 0) {
attachments.PoiID= PoiId;
}
if (VesselId != 0) {
attachments.VesselId = VesselId;
}
_context.Add(attachments);
await _context.SaveChangesAsync();
}
There is some confusion above i am using to store something else the
collection does not create this field it creates VesselsId with the
extra s this is what is not being filled in.
public int? VesselId { get; set; }
The collection creates this field
Add relation to FileAttachments model like this
public class FileAttachments {
...
[ForeignKey("Vessels")]
public int? VesselId { get; set; }
public Vessels Vessels { get; set; }
}

Adding more entries replaces everything instead of adding

Good day I am new in mongodb, I can successfully perform a CRUD, but now I want to dig deep into mongoDB. I have this JSON and I want it to update my database once it has a data, and create a new one if it doesn't exist, but what happens is it always replace my value for the "LeaderboardDetails".
Here is the MongoDB JSON:
{
"id" : "secretsomething",
"UserID" : "zgahsjd",
"category" : "testing",
"Score" : 2000,
"Badges" : 0,
"LeaderboardDetails": {
"id": "123123123213",
"ScoreForDay": 10000,
"BadgesForDay": 0
}
}
When I submit to update the "LeaderboardDetails" it should add a new entry if it doesn't exist, otherwise update the current one , but instead it replaces it.
Here is my code for PUT:
public void Update(string id, SomeModel newScore)
{
_record.ReplaceOne(scores => scores.id == id, newScore);
}
Here is the SomeModel Code:
[Required]
[JsonProperty(PropertyName = "UserID")]
public string UserID { get; set; }
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string id { get; set; }
[Required]
[JsonProperty(PropertyName = "category")]
public string category { get; set; }
[Required]
public int Score { get; set; }
[Required]
public int Badges { get; set; }
public class LeaderboardIDToSend
{
public string id;
public string ScoreForDay;
public string BadgesForDay;
public LeaderboardIDToSend(string _id, string _score, string _badges)
{
id = _id;
ScoreForDay = _score;
BadgesForDay = _badges;
}
}
[Required]
public LeaderboardIDToSend LeaderboardDetails;
Looking at your json, leaderBoardDetails is an object, but it should be a list of objects, that is the first modification you should do, second, in order for you to add an item to set, you should use Builders<T>.Update.AddToSet(c => c.leaderBoardDetails, leaderboardDto), now regarding your concern, you want to upsert the object, as far as I know, and looking at Array Update Operators, there is no such operator, so you will have to do this manually, you need to load all your existing leader, then check if this id exist, if so, you need to update its values, and then Update the whole list (leaderBoardDetails), if it doesn't exist, you can simple use AddToSet operator

Storing list of custom objects in Entity Framework

Started to learn asp.net and DB manipulations. Trying to implement some simple functionality - two models, one has list of references to another.
Here is an error that I currently get:
An exception occurred while initializing the database. See the InnerException for details.
Inner exception:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
My models:
public class Killer
{
public Killer(string name, string biography)
{
Name = name;
Biography = biography;
KillerId = Guid.NewGuid();
}
public Guid KillerId { get; set; }
public string Name { get; set; }
public string Biography { get; set; }
public virtual Contract Contract { get; set; }
}
public class Contract
{
public Contract(Status status, Killer target, string description, params Killer[] targets)
{
ContractId = Guid.NewGuid();
this.status = status;
Target = target;
Description = description;
Killers = new HashSet<Killer>();
foreach (var t in targets) Killers.Add(t);
}
public Guid ContractId { get; set; }
public enum Status { active, done, failed, rejected, abandoned }
public Status status { get; set; }
public Killer Target { get; set; }
public string Description { get; set; }
//[ForeignKey("ContractID")]
public virtual ICollection<Killer> Killers { get; set; }
}
In context I initialize db with lists of objects
public class KillerContext : DbContext
{
public DbSet<Killer> Killers { get; set; }
public DbSet<Contract> Contracts { get; set; }
}
In controller I do:
KillerContext k = new KillerContext();
public ActionResult Index()
{
var contracts = k.Contracts.ToList();
ViewBag.contracts = contracts;
return View();
}
In Global.asax:
Database.SetInitializer(new KillerContextInitialization());
Here is how I enter first data in db:
public sealed class KillerContextInitialization : DropCreateDatabaseAlways<KillerContext>
{
protected override void Seed(KillerContext db)
{
List<Killer> killers = new List<Killer>();
//List<Contract> contracts = new List<Contract>();
killers.Add(new Killer(name: "Ivan Firstein", biography: "He was born in the shadows."));
killers.Add(new Killer(name: "Oleg Gazmanov", biography: "test man"));
db.Contracts.Add(new Contract(
Contract.Status.active,
killers.SingleOrDefault(x => x.Name == "Ivan Firstein"),
"KILL OR BE KILLED. As always with love.",
killers.SingleOrDefault(x => x.Name == "Oleg Gazmanov")
));
db.Killers.AddRange(killers);
base.Seed(db);
}
}
Looks like you need add ForeignKey attribute for killer Model, and store this key in property ContractId:
public class Killer
{
[ForeignKey(nameof(ContractId)] //Name of added property in line below
public Contract Contract { get; set; } //no need "virtual"
public Guid? ContractId { get; set; }
// other properties...
}
public class Contract
{
[ForeignKey("ContractId")] //Name of added property in Killer Model
public virtual ICollection<Killer> Killers { get; set; }
// other code...
}
EDIT
You should do something similar to the Contract.Target property:
[ForeignKey(nameof(TargetId)]
public Killer Target { get; set; }
public Guid TargetId { get; set; }
For enum types you should add attributes like this:
[Column(nameof(status), TypeName = "int")]
public Status status { get; set; }
Find out that problem was in public Killer Target { get; set; }
When i was adding data, that field was considered as NOT NULL, and all what i need to do, is save changes after filling killers, like so:
public sealed class KillerContextInitialization : DropCreateDatabaseAlways<KillerContext>
{
protected override void Seed(KillerContext db)
{
List<Killer> killers = new List<Killer>();
killers.Add(new Killer(name: "Ivan Firstein", biography: "He was born in the shadows."));
killers.Add(new Killer(name: "Oleg Gazmanov", biography: "test man"));
db.SaveChanges(); // - save killers first, then add them to contract
db.Contracts.Add(new Contract(
Contract.Status.active,
killers.SingleOrDefault(x => x.Name == "Ivan Firstein"),
"KILL OR BE KILLED. As always with love.",
killers.SingleOrDefault(x => x.Name == "Oleg Gazmanov")
));
db.Killers.AddRange(killers);
base.Seed(db);
}
}

Entity Framework class instantiation behavior

I am facing a problem where my entity framework keeps behaving weirdly when I try to instantiate any class. I am trying to use the default usermanager behaviour to store data in my database. Once I start instantiating a new notification before it adds that notification to the list of notifications available in the application user class it persists those changes and process an error from entity framework saying that there is a multiplicity problem, how can I tell entity framework to not persist changes once I instantiate a class cf here is my controller code :
public string AddFriend(string AddedUserId)
{
var AddedUser = UserManager.FindById(AddedUserId);
var AddingUser = UserManager.FindById(User.Identity.GetUserId());
var friendship = new Friend(AddingUser, AddedUser) { IsInvitation = true };
AddingUser.Friends.Add(friendship);
AddedUser.Notifications.Add(new Notification(AddingUser, "Friend Invitation",
"The user " + AddingUser.FirstName + " " + AddingUser.LastName +
" Sent you a friend invitation", friendship));
UserManager.Update(AddedUser);
UserManager.Update(AddingUser);
return "Friend was added successfully";
}
my Notification class :
[Table("Notifications")]
public class Notification
{
[Key]
public int NotificationId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[Required]
public ApplicationUser AssociatedUser { get; set; }
public Friend AssociatedFrienship { get; set; }
public GroupMember AssociatedGroup { get; set; }
public ChannelMember AssociatedChannel { get; set; }
public Message AssociatedMessage { get; set; }
public bool Consulted { get; set; }
public Notification()
{
}
public Notification(ApplicationUser associatedUser, string title, string content, Friend associatedFriend = null, GroupMember associatedGroup = null, ChannelMember associatedChannel = null, Message associatedMessage = null)
{
AssociatedUser = associatedUser;
Title = title;
Content = content;
AssociatedChannel = associatedChannel;
AssociatedGroup = associatedGroup;
AssociatedFrienship = associatedFriend;
AssociatedMessage = associatedMessage;
Consulted = false;
}
}
my ApplicationUser class:
public partial class ApplicationUser : IdentityUser
{
public virtual List<Notification> Notifications { get; set; }
}
my FluentAPI code :
modelBuilder.Entity<Notification>()
.HasRequired(c => c.AssociatedUser)
.WithMany(c => c.Notifications);
Thanks in advance!
You don't have any foreign key to link AssociatedUser. Try adding a property to link Notification to ApplicationUser using foreign key. Like
public class Notification
{
//rest of properties
//change int to whatever type your primary key is in
//ApplicationUser class. I have Guid for example.
public int ApplicationUser AssociatedUserId {get;set;}
}
Then try modifying configuration like this:
modelBuilder.Entity<Notification>()
.HasRequired(c => c.AssociatedUser)
.WithMany(c => c.Notifications)
.HasForeignKey(n=>n.AssociatedUserId);

"Cannot insert the value NULL into column" with a non-null value

This is the code I have:
Controller action method:
[HttpPost]
public ActionResult Create(Goal goal)
{
if (ModelState.IsValid)
{
repository.SaveGoal(goal);
return View("Index");
}
else
{
return View(goal);
}
}
Model:
public class Goal
{
[Required]
public int GoalId { get; set; }
[Required]
public string Name { get; set; }
[Required]
[HiddenInput(DisplayValue = false)]
public decimal Latitude { get; set; }
[Required]
[HiddenInput(DisplayValue = false)]
public decimal Longitude { get; set; }
[Required]
public bool IsPrivate { get; set; }
}
Repository:
public class EFGoalRepository : IGoalRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<Goal> Goals
{
get { return context.Goals; }
}
public void SaveGoal(Goal goal)
{
context.Goals.Add(goal);
context.SaveChanges(); // the line which causes the exception
}
}
The problem: When I try to save a new Goal object with GoalId set to 0, I get the following error:
Cannot insert the value NULL into column 'GoalId', table 'TravelGoals.dbo.Goals'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I'm still new at ASP.NET MVC, but I believe this worked when I tried it a month ago with a different project.
All the values in my Goal object are valid (non-null, Name is of correct length). The GoalId property is set to 0, so it is not null either. I thought that Entity Framework would automatically assign a value to it.
What can I do to make this work?
What I needed to do was setting the column as identity in SQL Server.
Probably the simplest way to do this (assuming you're using Visual Studio):
Open the SQL Server Object Explorer
Double-click the table you want to edit (or right-click and select View Designer)
Open the Properties window
Select the column in the Identity Column property as shown below
Problem is GoalId is not identity.Put this attribut on GoalId
[Key]
public int GoalId { get; set; }
If your EF version is lower than 5 use this:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int GoalId { get; set; }

Categories

Resources