How to create entity with nested via LINQ to SQL - c#

I got one entity linked with another:
[Table(Name = "Employees")]
public sealed class Employee
{
[Column(Name = "Id", UpdateCheck = UpdateCheck.Never, IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY")]
public int Id { get; set; }
[Column(Name = "Phone", UpdateCheck = UpdateCheck.Never, DbType = "Char(20)")]
public string Phone { get; set; }
[Column(Name = "UserId", UpdateCheck = UpdateCheck.Never, DbType = "Int NOT NULL")]
public int UserId { get; set; }
[Association(Storage = "_user", ThisKey = "UserId")]
public User User
{
get { return _user.Entity; }
set { _user.Entity = value; }
}
private EntityRef<User> _user;
}
[Table(Name = "Users")]
public sealed class User
{
[Column(Name = "Id", UpdateCheck = UpdateCheck.Never, IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY")]
public int Id { get; set; }
[Column(Name = "LastName", UpdateCheck = UpdateCheck.Never, DbType = "NVarChar(100)")]
public string LastName { get; set; }
[Column(Name = "FirstName", UpdateCheck = UpdateCheck.Never, DbType = "NVarChar(100)")]
public string FirstName { get; set; }
}
Then I want to create an employee:
var entity = new Employee
{
Phone = "Some",
User = new User
{
FirstName = "Some",
LastName = "Some"
}
};
context.GetTable<Employee>().InsertOnSubmit(entity);
context.SubmitChanges();
And got this:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Employees_Users"
Is it posible to create linked entities in LINQ to SQL?

Try specifying the OtherKey property of the AssociationAttribute as well. If not specified, it will default to the key of the related class, but in your case the names of the keys in the different classes are different (UserId vs Id).
[Association(Storage = "_user", ThisKey = "UserId", OtherKey="Id")]
public User User
{
get { return _user.Entity; }
set { _user.Entity = value; }
}
private EntityRef<User> _user;

Related

Linq2SQL not inserting related entity

I'm trying to insert into two releated tables with linq2sql but my code only inserts one entity(Email), I dont get any exceptions - just the other entity (attachment) is not inserted.
I think I have an mistake somewhere in the association, but i cant figure out how to set it up properly.
Thanks for help.
Insert code:
using (TransactionScope main_transaction = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(120)))
{
foreach (var attachment in attachmets)
email.Attachments.Add(attachment);
_emails.InsertOnSubmit(email);
_context.SubmitChanges();
main_transaction.Complete();
}
Pocos:
[Table(Name = "maily")]
internal class Email
{
private EntitySet<Attachment> _attachments;
public Email()
{
this._attachments = new EntitySet<Attachment>();
}
[Column(IsPrimaryKey = true, IsDbGenerated = true, Name = "ID_mailu", AutoSync = AutoSync.OnInsert)]
public virtual int ID_mailu { get; set; }
[Association(Storage = "_attachments", OtherKey = "id_mailu")]
public ICollection<Attachment> Attachments
{
get { return _attachments.ToList(); }
set { _attachments.Assign(value); }
}
}
[Table(Name = "MailPrilohy")]
internal class Attachment
{
private EntityRef<Email> _email;
public Attachment()
{
_email = default(EntityRef<Email>);
}
[Column(IsPrimaryKey =true, IsDbGenerated = true, Name = "id_prilohy", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int Id_Prilohy { get; set; }
[Column(Name = "id_mailu", CanBeNull = false, IsDbGenerated = true)]
public int id_mailu { get; set; }
[Association(Storage = "_email", ThisKey = "id_mailu", OtherKey = "ID_mailu", IsForeignKey = true)]
public Email Email
{
get { return _email.Entity; }
set { _email.Entity = value; }
}
}
}
So I have just solved the problem...
The problem was in several places.
1s was the association missed foreign key attribute ..
[Association(Storage = "_email", ThisKey = "id_mailu", OtherKey = "ID_mailu", IsForeignKey = true)]
public Email Email
{
get { return _email.Entity; }
set { _email.Entity = value;}
}
Next, i was supposed to insert attachments -> not the email.
_context.Attachments.InsertAllOnSubmit(attachmets);
Can you try to see if this works for you?
using (TransactionScope main_transaction = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(120)))
{
foreach (var attachment in attachmets)
attachment.Email = email; // only this line changed
_emails.InsertOnSubmit(email);
_context.SubmitChanges();
main_transaction.Complete();
}

NotMapped prop Validation failed for one or more entities. See 'EntityValidationErrors' property for more details

good day ..
i created a model that has an property with [Notmapped] DataAnnotations and i created another class inherit from this model with same property but i add required DataAnnotations the problem is when i delete i got error "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
"
My Model :
[Key]
[Display(AutoGenerateField = true, AutoGenerateFilter = true, Description = "IDDescription", GroupName = "IDGroupName", Name = "IDName", ShortName = "IDShortName", Prompt = "IDPrompt", Order = 50, ResourceType = typeof(Resources.BaseEntity))]
public long ID { get; set; }
[StringLength(207, ErrorMessageResourceName = "StringTooMuch", ErrorMessageResourceType = typeof(Resources.BaseSlider))]
[Required(AllowEmptyStrings = false, ErrorMessageResourceName = "DetailsRequired", ErrorMessageResourceType = typeof(Resources.BaseSlider))]
[Display(Name = "Description", ResourceType = typeof(Resources.BaseSlider))]
public string Description { get; set; }
[NotMapped]
public string ShortDescription
{
get
{
if (Description.Length <= 207)
{
return Description;
}
return Description.Substring(0, 207);
}
}
[Display(Name = "HasBTN", ResourceType = typeof(Resources.BaseSlider))]
public bool HasBTN { get; set; }
[Display(Name = "Is Image Dark")]
public bool IsDark { get; set; }
[Display(Name = "Link", ResourceType = typeof(Resources.BaseSlider))]
public string Link { get; set; }
[Display(Name ="Slider Type")]
public long SliderTypeID { get; set; }
[NotMapped]
//[ImageValidation(".jpg,.png,.japg", OriginalWidth = 1920, OriginalHeight = 600)]
[Display(AutoGenerateField = true, AutoGenerateFilter = true, Description = "ImagePathDescription", Name = "ImagePathName", ResourceType = typeof(Resources.BaseMore))]
public virtual HttpPostedFileBase ImagePathFile { get; set; }
#endregion
#region Relations
public virtual IList<BaseSliderPhotoUpload> Photos { get; set; }
public virtual BaseLookup SliderType { get; set; }
#endregion
public BaseSlider()
{
Photos = new List<BaseSliderPhotoUpload>();
}
and the class i created :
public class BaseSliderCreate : BaseSlider
{
#region Data
[NotMapped]
[Required]
//[ImageValidation(".jpg,.png,.japg", OriginalWidth = 1920, OriginalHeight = 600)]
[Display(AutoGenerateField = true, AutoGenerateFilter = true, Description = "ImagePathDescription", Name = "ImagePathName", ResourceType = typeof(Resources.BaseMore))]
public override HttpPostedFileBase ImagePathFile { get; set; }
#endregion
}
in delete actionresult code :
public ActionResult DeleteConfirmed(Guid id)
{
BaseSlider SliderObject = db.Sliders.Where(x => x.GUID == id && x.Deleted == null).FirstOrDefault();
SliderObject.Deleted = DateTime.Now;
SliderObject.DeletedByID = _CurrentUser.ID;
// Delete All Photos
DeletePhoto DeletePhoto = new DeletePhoto();
var DeletedPhotoName = new List<string>();
foreach (var name in SliderObject.Photos)
{
DeletedPhotoName.Add(name.FileName);
}
if (DeletePhoto.PhotoDeleted("Slider", DeletedPhotoName))
{
try
{
db.SliderPhotos.RemoveRange(SliderObject.Photos);
db.Entry(SliderObject).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception ex)
{
ErrorList.Add(ex.Message);
throw;
}
}
else
{
ErrorList.Add(DeletePhoto.ErrorMessage);
}
ViewBag.ErrorList = ErrorList;
return RedirectToAction("Delete", new { id = SliderObject.GUID });
}
when i save change i got error
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
i checked i found the EntityValidationErrors is that ImagePathFile is required..
thanks for helping my and i apologist for my bad English

Self-Reference in OOP & C#

consider below table :
FkName SchemaName Table Column RefTable RefColumn
FK_Factory_Person dbo Factory PersonId Person Id
FK_Car_Person dbo Car PersonId Person Id
FK_Factory_Car dbo Factory CarId Car Id
I want to create Dependency class for saving the dependent data
so I wrote a self-reference class that any dependency can have dependencies.
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
but I dont know how fill class :
- TableName=Person , ColumnName=Id , Dependencies=Factory,Car
--TableName=Car , ColumnName=Id , Dependencies=Factory
Factory
'
'---- Person
'---- Car
Car
'
'---- Person
Can anyone help me for filing Dependency class recursively ?
SOLUTION:
public class Link
{
public string FKName { get; set; }
public string SchemaName { get; set; }
public string Table { get; set; }
public string Column { get; set; }
public string RefTable { get; set; }
public string RefColumn { get; set; }
}
public class Dependency
{
public string TableName { get; set; } // RefTable
public string ColumnName { get; set; } //RefColumn
public List<Dependency> Dependencies { get; set; } // Table
}
private static void ProcessItem(Dependency target, List<Dependency> dictionary)
{
if(target.Dependencies != null)
foreach(var dep in target.Dependencies)
{
var children = dictionary.Where(x => x.TableName == dep.TableName).FirstOrDefault();
dep.Dependencies = children == null ? null : children.Dependencies;
ProcessItem(dep, dictionary);
}
}
public static List<Dependency> ProcessItems(List<Link> links)
{
var initial = links.GroupBy(x => new { x.RefTable, x.RefColumn })
.Select(x => new Dependency {
TableName = x.Key.RefTable,
ColumnName = x.Key.RefColumn,
Dependencies = x.Select(y => new Dependency {
TableName = y.Table,
ColumnName = y.Column
}).ToList()
}).ToList();
var js = new JavaScriptSerializer();
var temp = js.Deserialize<List<Dependency>>(js.Serialize(initial));
initial.ForEach(x => ProcessItem(x, temp));
return initial;
}
IMPLEMENTATION:
var links = new List<Link> {
new Link { FKName = "FK_Factory_Person", SchemaName = "dbo", Table = "Factory", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Car_Person", SchemaName = "dbo", Table = "Car", Column = "PersonId", RefTable = "Person", RefColumn = "Id" },
new Link { FKName = "FK_Factory_Car", SchemaName = "dbo", Table = "Factory", Column = "CarId", RefTable = "Car", RefColumn = "Id" },
new Link { FKName = "FK_TEST", SchemaName = "dbo", Table = "Person", Column = "TestId", RefTable = "Test", RefColumn = "Id" }
};
var answer = ProcessItems(links);
P.S. If you have circular dependency, StackOveflowException will be
thrown.

Combine contents of two files using LINQ to CSV

This is probably a dumb question, but I'm wondering how I would fill a list with the following data for a CSV file.
Here's the code so far,
class Info
{
[CsvColumn(Name = "Lease Name", FieldIndex = 1)]
public string leaseName2 { get; set; }
[CsvColumn(Name = "Field Name", FieldIndex = 2)]
public string fieldName2 { get; set; }
[CsvColumn(Name = "Reservoir", FieldIndex = 3)]
public string reservoir2 { get; set; }
[CsvColumn(Name = "Operator", FieldIndex = 4)]
public string operator2 { get; set; }
[CsvColumn(Name = "County", FieldIndex = 5)]
public string county2 { get; set; }
[CsvColumn(Name = "State", FieldIndex = 6)]
public string state2 { get; set; }
[CsvColumn(Name = "Majo", FieldIndex = 7)]
public string majo2 { get; set; }
[CsvColumn(Name = "Resv Cat", FieldIndex = 8)]
public string resvCat2 { get; set; }
[CsvColumn(Name = "Discount Rate", FieldIndex = 9)]
public double disRate2 { get; set; }
There are more columns I just did not want to list them all because that would be redundant. If anyone could help that would be greatly appreciated.
#GertArnold is right, you can use Union(). I used Concat() in my example. Union returns distinct records, Concat doesn't.
using System;
using System.Collections.Generic;
using System.Linq;
using LINQtoCSV;
namespace LinqCsvSandbox
{
class SampleData
{
[CsvColumn(Name = "ID", FieldIndex = 1)]
public string ID { get; set; }
[CsvColumn(Name = "PersonName", FieldIndex = 2)]
public string Name { get; set; }
public override string ToString()
{
return string.Format("{0}: {1}", ID, Name);
}
}
class Program
{
static void Main(string[] args)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = false,
FileCultureName = "en-us",
EnforceCsvColumnAttribute = true,
};
CsvContext cc = new CsvContext();
IEnumerable<SampleData> data1 = cc.Read<SampleData>("File1.csv", inputFileDescription);
IEnumerable<SampleData> data2 = cc.Read<SampleData>("File2.csv", inputFileDescription);
IEnumerable<SampleData> all = data1.Concat(data2);
// Uncomment to see the items printed
//foreach(var item in all)
// Console.WriteLine(item);
cc.Write(all, "All.csv");
}
}
}
In my example, File1.csv contains
1,Fred
2,Wilma
File2.csv contains
3,Tango
4,Cash
And the resulting All.csv contains
ID,PersonName
1,Fred
2,Wilma
3,Tango
4,Cash
For those unfamiliar, Linq to CSV is available as a package from NuGet.
Here are a couple of ways, the first is just using an object initializer, the second transfers a small list to the your CSV list:
List<Info> infoList = new List<Info>
{
new Info()
{
leaseName2 = "x"
}
};
List<string> stringList = new List<string> {"xy", "zz"};
infoList.AddRange(stringList.Select(stringVal => new Info()
{
leaseName2 = stringVal
}));

MVC - Seeding GUID and table key

During seeding in MVC how can I prevent GUIDs being generated in the database?
This is my class:
[Table("Languages")]
public class Language
{
[Key]
public Guid ID { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 0)]
public string Name { get; set; }
[Required]
[StringLength(10, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 0)]
public string Code { get; set; }
[DefaultValue(true)]
public bool IsEnabled { get; set; }
}
And this is my seed method:
protected override void Seed(SunLite.Models.SunLiteDBContext context)
{
public static SunLiteDBContext Run(SunLiteDBContext context)
{
context.Languages.AddOrUpdate
(
x => x.ID,
new Language { Name = "English", Code = "en-gb", ID = Guid.Parse("{fab5422a-f63d-4042-b7b1-705f69854bc9}"), IsEnabled = true },
new Language { Name = "Spanish", Code = "es", ID = Guid.Parse("{24380e18-02bf-4668-87ee-b2514d17f384} "), IsEnabled = true },
new Language { Name = "German", Code = "de", ID = Guid.Parse("{2c05c682-704f-43a4-864b-742ae359aa30}"), IsEnabled = true },
new Language { Name = "French", Code = "fr", ID = Guid.Parse("{bf929fe3-67a0-425c-81d2-1ef554affc7c} "), IsEnabled = true },
new Language { Name = "Turkish", Code = "tr", ID = Guid.Parse("{9d09cb45-3d0d-4238-a903-96c4f17481a1} "), IsEnabled = true }
);
}
}
At the moment this data is added to the database each time with new guids, not the ones I specified.
You can add attribute [DatabaseGenerated(DatabaseGeneratedOption.None)] to your ID property. It should help.

Categories

Resources