delete many to many entity framework [duplicate] - c#

I'm using POCOs in combination with EF4 and some entities are in many-to-many relationships, in my case objects of class User and objects of class PrivilegeGroup.
This is how class User looks like:
public class User
{
public int UserID { set; get; }
public string UserName { get; set; }
public string UserPassword { get; set; }
public bool IsActive { get; set; }
public List<PrivilegeGroup> PrivilegeGroups { get; set; }
}
And this is how class PrivilegeGroup looks like:
public class PrivilegeGroup
{
public int PrivilegeGroupID { get; set; }
public string Name { get; set; }
public List<User> Users { get; set; }
public List<HasPrivilege> HasPrivileges { get; set; }
}
I have extended ObjectContext class
as follows:
public class AdminMDSContext : ObjectContext
{
public AdminMDSContext(string connectionString)
: base(connectionString)
{
this.DefaultContainerName = "MDSUsers_Entities";
_users = CreateObjectSet<User>();
_privilegeGroups = CreateObjectSet<PrivilegeGroup>();
}
private ObjectSet<User> _users;
private ObjectSet<PrivilegeGroup> _privilegeGroups;
public ObjectSet<User> Users
{
get { return _users; }
}
public ObjectSet<PrivilegeGroup> PrivilegeGroups
{
get { return _privilegeGroups; }
set { _privilegeGroups = value; }
}
}
Querying and insertion of these entities are working fine, but deletion is making problem, i.e. I want to remove PrivilegeGroup from one User without db roundtrip, but I don't know how to do it.
Can anyone please help me?

Interesting question. Here is how u do it.
var user = new User { UserId = 1 };
var admin = new Privilege { PrivilegeId = 1 };
user.Privileges.Add(admin);
db.Users.Attach(user);
user.Privileges.Remove(admin);
db.SaveChanges();
There are total of 4 different approaches to solving the same problem. but i think from what u are telling me, this should suffice but if u need more info, you can ping me directly through mail

Related

Query Parent Class EF inheritence linq query

Hello everyone so here is my basic EF class structure:
public abstract class StandardEngineeredModel
{
[Key]
public string ModelNumber { get; set; }
public int VoltageInput { get; set; }
}
public class DualRatedInputEngineeredModel : StandardEngineeredModel
{
public int SinglePhaseVoltageInput { get; set; }
public string SinglePhaseHzInput { get; set; }
public decimal SinglePhaseAmpsInput { get; set; }
public bool SeparateInput { get; set; }
}
And my context:
public class LabelPrintingContext : DbContext
{
public virtual DbSet<StandardEngineeredModel> StandardEngineeredModels { get; set; }
}
What I am trying to do is query for a StandardEngineeredModel. Here is an example of a query I tried:
public StandardEngineeredModel GetEngineeredOrder(string modelNumber)
{
using (context = new LabelPrintingContext())
{
return (from s in context.StandardEngineeredModels
where s.ModelNumber == modelNumber
select s).FirstOrDefault();
}
}
But when executing this it says invalid column name SeparateInput which seems to be happening because of the extra column being added to my StandardEngineeredModels table due to the DualRatedInputEngineeredModel inheriting from it. Not sure how to go about this, I don't want to return an Iqueryable, but no matter what I try it tells me the SeparateInput is an invalid column name.
I also tried casting it first and get the same error:
public StandardEngineeredModel GetEngineeredOrder(string modelNumber)
{
using (context = new LabelPrintingContext())
{
return (from s in context.StandardEngineeredModels.OfType<StandardEngineeredModel>()
where s.ModelNumber == modelNumber
select s).FirstOrDefault();
}
}
Do I need to make a DTO or something? Am I just doing this completely wrong?
Thanks in advance for any opinions / help!

WPF Entity Framework Foreign key won't load it's value in a DataGrid

I am using Entity Framework code first with fluent API I have an items table with foreign keys from users and units tables
but when I load the table to ObservableCollection then bind it to a datagrid the table normal column load it's data normally into the datagrid excpet for the foreign keys which show nothing but when i insert a break point to see the data inside the ObservableCollection I can see that every thing from Users and Units table is there
private void MainContentsWindow_ContentRendered(object sender, EventArgs e)
{
using (var db2 = new DataContext())
{
var AllItems2 = new ObservableCollection<Model.Items.Item>(db2.Items);
ItemsDataGrid.ItemsSource = AllItems2;
}
}
Users
public class User
{
public User()
{
Id = Guid.NewGuid();
IsActive = false;
}
public Guid Id { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public UserGroup Group { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Items.Item> Items { get; set; } = new List<Items.Item>();
}
public enum UserGroup
{
Administrator = 1,
User,
Unknown
}
base
public class NormalBaseModel : CommonBase
{
public NormalBaseModel()
{
Id = new Guid();
CreateDate = DateTime.Now;
EditDate = null;
}
public Guid Id { get; set; }
public string Notes { get; set; }
public virtual User CreateBy { get; set; }
public DateTimeOffset? CreateDate { get; set; }
public virtual User EditBy { get; set; }
public DateTimeOffset? EditDate { get; set; }
}
items
public class Item : NormalBaseModel
{
public string NameAr { get; set; }
public string NameEn { get; set; }
public int? ManualId { get; set; }
public string Barcode { get; set; }
public byte?[] Image { get; set; }
public virtual Unit Unit { get; set; }
public string MadeIn { get; set; }
public bool IsSerail { get; set; }
public bool IsExpire{ get; set; }
}
Here is a test project on Github
https://github.com/ahmedpiosol/psychic-parakeet.git
https://imgur.com/a/zimd4
When you load your items via EF it needs to create new instances of User and Item. Behind the scenes, EF will call the constructor for each new instance. Your problem is in your constructors:
public User()
{
Id = Guid.NewGuid(); // <- here
}
Your constructor reassigns a new ID each time an instance is created, this will break the referential integrity and cause all sorts of other problems.
Your code doesn't know the difference between creating a new User and recreating a User instance from the database.
I suggest removing the assignments from inside your constructor and placing this either in a static Create method or place wherever you are creating a new User or Item.
p.s. WPF is irrelevant to your problem here.
Fluent API needs to specify foreign key in code, something like
modelBuilder.Entity<Items>()
.HasRequired(o => o.User)
.WithMany(c => c.Items)
.HasForeignKey(o => o.UserId);

Mapping composite poco to EF objectcontext entities

I have to produce an output from 3 separate tables(with a couple of fields from each table) into 1 output. I have a class that represents that output. The data is pulled from linq query of EF 6.1.x ObjectContext(Im stuck with using ObjectContext due to the nature of my clients needs....) entities (the 3 classes properly joined in the query) to a list of the new class (List<>). I populate a grid and all is fine. However the user wants to edit the data in the grid and now I need to push those new changes back.
My question is this: Can I map my new class back to the entities field to field? Or am I stuck with iterating through the collection and updating the tables individually? I thought I could map but I haven't run across anything that substantiates this.
Could you not do this using the "Proxy" pattern?
I've done a 2 entity + Wrapper example pseudo example below.
EF would "Save" the SuperWrapper.DeptProxy and the SuperWrapper.EmpProxy.
public partial class DepartmentEFEntity {
public virtual Guid? DepartmentUUID { get; set; }
public virtual string DepartmentName { get; set; }
public virtual ICollection<EmployeeEFEntity> Employees { get; set; }
}
public partial class EmployeeEFEntity
{
public virtual Guid? ParentDepartmentUUID { get; set; }
public virtual Guid? EmployeeUUID { get; set; }
public virtual DepartmentEFEntity ParentDepartment { get; set; }
public virtual string SSN { get; set; }
}
public class SuperWrapper
{
internal DepartmentEFEntity DeptProxy { get; private set; }
internal EmployeeEFEntity EmpProxy { get; private set; }
public SuperWrapper(DepartmentEFEntity dept, EmployeeEFEntity emp)
{
this.DeptProxy = dept;
this.EmpProxy = emp;
}
public string DepartmentName
{
get { return null == this.DeptProxy ? string.Empty : this.DeptProxy.DepartmentName; }
set { if(null!=this.DeptProxy{this.DeptProxy.DepartmentName =value;}}
}
public string EmployeeSSN
{
get { return null == this.EmpProxy ? string.Empty : this.EmpProxy.SSN; }
set { if(null!=this.EmpProxy{this.EmpProxy.SSN =value;}}
}
}

EF6 Interceptor to set a value on Insert or Update

I am having troubles trying to figure out how to use the EF6 interceptors to set a value on Insert/Update.
What I wanted to do is to have an interceptor to automatically create a new instance of Audit like so:
public class FooContext : DbContext
{
public DbSet<Invoice> Invoices { get; set; }
public DbSet<Audit> Audits { get; set; }
}
public class Invoice
{
public int Id { get; set; }
public string Name { get; set; }
public Audit AuditAndConcurrencyKey { get; set; }
}
public class InvoiceItem
{
public int Id { get; set; }
public Invoice Header { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
//For legacy reasons. I know this design is wrong :(
public Audit AuditAndConcurrencyKey { get; set; }
}
public class Audit
{
public int Id { get; set; }
public int InstanceId { get; set; }
public string Message { get; set; }
}
[Test]
public void WillCreateAudit()
{
using (var db = new FooContext())
{
var inv = new Invoice {Name = "Foo Invoice"};
var invLine = new InvoiceItem {Header = inv, Price = 1, Name = "Apple"};
db.Invoices.Add(inv);
db.SaveChanges();
//Inceptors should figure out that we are working with "Invoice" and "InvoiceLine"
//And automatically create an "Audit" instance
Assert.That(inv.AuditAndConcurrencyKey != null);
Assert.That(invLine.AuditAndConcurrencyKey != null);
Assert.That(inv.AuditAndConcurrencyKey == invLine.AuditAndConcurrencyKey)
}
}
The first thing I checked is this example for SoftDeleteInterceptor. I don't think this is what I want because it looks like at the point where we are already generating the expression tree, we are no longer aware of the type of object you are working with.
I checked this example as well, but again, it looks like we are injecting strings instead of setting object references.
Ideally I want something like this:
public class AuditInterceptor
{
public void Intercept(object obj)
{
if (!(obj is Invoice) && !(obj is InvoiceItem))
return; //not type we are looking for, by-pass
//Set the audit here
}
}

Is possible to use generics in LINQ-to-SQL mapping?

Is there a way to define the following structure in a DataContext/DBML file?
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public EntitySet<IPermission> Permissions { get; set; }
}
public class User : IPermissionHolder
{
public int Id { get; set; }
public string Name { get; set; }
public EntitySet<Permission<User>> Permissions { get; set; }
}
public class Group : IPermissionHolder
{
public int Id { get; set; }
public string Name { get; set; }
public EntitySet<Permission<Group>> Permissions { get; set; }
}
public interface IPermissionHolder
{
int Id { get; set; }
}
public interface IPermission
{
Entity Entity { get; set; }
IPermissionHolder Holder { get; }
}
public class Permission<T> : IPermission where T : class, IPermissionHolder
{
public IPermissionHolder Holder
{
get { return PermissionHolder; }
}
public T PermissionHolder { get; set; }
public Entity Entity { get; set; }
}
If it's not possible, can you seggest another structure that fits my need?
Right now my DB is using two different tables for the GroupPermissions and the UserPermissions.
I don't like to have a common table where i have to add a "type" column... with two different table i have a much more strict control on the DB side.
Thanks for any help
P.S.: i'm still with the Framework 3.5, otherwise i could remove the IPermissionHolder interface and use co-variance
P.S.S.: asked also here, but no answer :(
http://social.msdn.microsoft.com/Forums/en/linqtosql/thread/04a03c68-79c0-4136-907c-f81440e78c45
EDIT:
i'm trying different things and i'm facing two main problems
1) I want to have a IEnumerable, but it will never works because i don't want only to get data, but also to push data and an object can not be covariant and contravariant at the same time.
So first of all i should choose: read or write.
2)Here the most difficult issue: how do i map TWO Association to a single property?
User:
[global::System.Data.Linq.Mapping.AssociationAttribute(Name = "User_Permission", Storage = "permissions", ThisKey = "Id", OtherKey = "UserId")]
public EntitySet<Permission<User>> Permissions{ ... }
Group
[global::System.Data.Linq.Mapping.AssociationAttribute(Name = "Group_Permission", Storage = "permissions", ThisKey = "Id", OtherKey = "GroupId")]
public EntitySet<Permission<Group>> Permissions { ... }
Permission
[global::System.Data.Linq.Mapping.AssociationAttribute(Name = "???", Storage = "holder", ThisKey = "HolderId", OtherKey = "Id", IsForeignKey = true)]
public T PermissionHolder { ... }
Maybe i should call the Asscoiation "Holder_Permission"?!?
I tried with many different approach. I can say that with LINQ-TO-SQL is not possible to have generic mapping.
I will try with the Linq-To-Entity.

Categories