Want help on inheritance of forms in c# - c#-3.0

I have created a form which prints the average and grades of a student. I want to inherit the properties of that form to another form. How can it be achieved? I am a beginner in c#.Please help.
this is the form from which i want to inherit
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace formstud
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
String str = textBox1.Text;
textBox2.Text = str;
}
private void button1_Click_1(object sender, EventArgs e)
{
int a, b, c, d;
a = Convert.ToInt32(textBox3.Text);
b = Convert.ToInt32(textBox4.Text);
c = Convert.ToInt32(textBox5.Text);
d = (a + b + c) / 3;
if (d <= 50 && d >= 40)
{
label1.Text = "A";
}
else if (d >= 30 && d <= 40)
{
label1.Text = "B";
}
else
label1.Text = "C";
label7.Text = Convert.ToString(d);
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label7_Click(object sender, EventArgs e)
{
}
}
}
this is the derived form i created
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace formstud
{
public partial class Form2 : formstud.Form1
{
public Form2()
{
InitializeComponent();
}
}
}

You need to do the following :-
public partial class Form1 : Form
{
public int PropertyA { get; set; }
public int PropertyB { get; set; }
public Form1()
{
InitializeComponent();
}
}
public partial class Form2 : Form1
{
public Form2()
{
InitializeComponent();
PropertyA = 1;
PropertyB = 2;
}
}
A quick Explanation on this. In Form1, I have created two Public properties, PropertyA and PropertyB.
I then create Form2, only this time i inherit from the Form1 class, rather than Form. This gives me access to PropertyA & PropertyB, without declaring them.
This is just one example, you could draw up an interface, which is kinda like a contract, that suggests any form I build, where i quote this interface, it must implement these properties.
public interface IProperties
{
int PropertyA { get; set; }
int PropertyB { get; set; }
}
Now Form1 & Form2 can just look like this :-
public partial class Form2 : Form, IProperties
{
public Form2()
{
InitializeComponent();
}
public int PropertyA { get; set; }
public int PropertyB { get; set; }
}

Related

How to declare a parent child relationship when both tables are TPH and the relationship is in the base classes?

My problem relates to sales orders and sales invoices but I find it easier to think of pets and their offspring... without creating a full pedigree model.
My DbContext
using System;
using DevExpress.ExpressApp.EFCore.Updating;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
using DevExpress.Persistent.BaseImpl.EF;
using DevExpress.ExpressApp.Design;
using DevExpress.ExpressApp.EFCore.DesignTime;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DevExpress.ExpressApp.DC;
using System.Collections.Generic;
namespace Pets.Module.BusinessObjects
{
[TypesInfoInitializer(typeof(PetsContextInitializer))]
public class PetsEFCoreDbContext : DbContext
{
public PetsEFCoreDbContext(DbContextOptions<PetsEFCoreDbContext> options) : base(options)
{
}
public DbSet<Cat> Cats { get; set; }
public DbSet<Dog> Dogs { get; set; }
public DbSet<Kitten> Kittens { get; set; }
public DbSet<Puppy> Puppys { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Pet>()
.HasDiscriminator(x=> x.IsCat)
.HasValue<Cat>(true)
.HasValue<Dog>(false);
modelBuilder.Entity<BabyPet>()
.HasDiscriminator(x => x.IsCat)
.HasValue<Kitten>(true)
.HasValue<Puppy>(false);
modelBuilder.Entity<Puppy>().HasOne(x => x.Parent).WithMany(x => x.Puppies);
modelBuilder.Entity<Kitten>().HasOne(x => x.Parent).WithMany(x => x.Kittens);
}
}
}
My classes
public abstract class Pet
{
[Key] public int Id { get; set; }
public string Name { get; set; }
public bool? IsCat { get; set; }
}
public abstract class BabyPet
{
[Key] public int Id { get; set; }
public int ParentPetId { get; set; }
[ForeignKey("ParentPetId")]
public virtual Pet Parent { get; set; }
public string Name { get; set; }
public bool? IsCat { get; set; }
}
public class Kitten : BabyPet
{
new public virtual Cat Parent { get; set; }
}
public class Dog : Pet
{
public Dog()
{
Puppies = new List<Puppy>();
}
[Aggregated]
public virtual List<Puppy> Puppies { get; set; }
}
public class Cat : Pet
{
public Cat()
{
Kittens = new List<Kitten>();
}
[Aggregated]
public virtual List<Kitten> Kittens { get; set; }
}
public class Puppy : BabyPet
{
new public virtual Dog Parent { get; set; }
}
Also there is
public class PetsContextInitializer : DbContextTypesInfoInitializerBase
{
protected override DbContext CreateDbContext()
{
var optionsBuilder = new DbContextOptionsBuilder<PetsEFCoreDbContext>()
.UseSqlServer(#";");
return new PetsEFCoreDbContext(optionsBuilder.Options);
}
}
However this creates the following structure in BabyPet
Where as I just want
[Update]
I was able to get the structure I want by specifying the foreignkey in OnModelCreating
modelBuilder.Entity<Puppy>().HasOne(x => x.Parent).WithMany(x => x.Puppies).HasForeignKey(x=>x.ParentPetId);
modelBuilder.Entity<Kitten>().HasOne(x => x.Parent).WithMany(x => x.Kittens).HasForeignKey(x => x.ParentPetId);
However when I try to add a Kitten to a cat via the XAF Winforms UI I get:
Unable to cast object of type 'SimplePets.Module.BusinessObjects.Kitten' to type 'SimplePets.Module.BusinessObjects.Puppy'.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.get_Item(IPropertyBase propertyBase)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.GetCurrentValue(IPropertyBase propertyBase)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.TryAddPropertyNameToCollection(InternalEntityEntry entity, ICollection`1 propertiesToCheck, IPropertyBase property)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.TryAddPropertyNameToCollection(InternalEntityEntry entity, IProperty property, ICollection`1 propertiesToCheck)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.GetPropertiesToCheck(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckReadWritePermissionsForNonIntermediateObject(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckReadWritePermissions(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.CheckIsGrantedToSave(InternalEntityEntry entity)
at DevExpress.EntityFrameworkCore.Security.NetStandard.ChangeTracking.SecurityStateManager.GetEntriesToSave(Boolean cascadeChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at DevExpress.ExpressApp.EFCore.EFCoreObjectSpace.DoCommit()
at DevExpress.ExpressApp.BaseObjectSpace.CommitChanges()
at DevExpress.ExpressApp.Win.SystemModule.WinModificationsController.Save(SimpleActionExecuteEventArgs args)
at DevExpress.ExpressApp.SystemModule.ModificationsController.saveAction_OnExecute(Object sender, SimpleActionExecuteEventArgs e)
at DevExpress.ExpressApp.Actions.SimpleAction.RaiseExecute(ActionBaseEventArgs eventArgs)
at DevExpress.ExpressApp.Actions.ActionBase.ExecuteCore(Delegate handler, ActionBaseEventArgs eventArgs)
I put my example on GitHub here
Docs link about relationships here and tph inheritance is here
I think I must have the data structures correct after my update to onModelCreating. That is :
modelBuilder.Entity<Puppy>().HasOne(x => x.Parent).WithMany(x => x.Puppies).HasForeignKey(x=>x.ParentPetId);
modelBuilder.Entity<Kitten>().HasOne(x => x.Parent).WithMany(x => x.Kittens).HasForeignKey(x => x.ParentPetId);
I was able to work around the Cast Object error by using DBContext instead of ObjectSpace
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using SimplePets.Module.BusinessObjects;
using System.Linq;
namespace SimplePets.Module.Win.Controllers
{
public class KittenViewController : ViewController
{
SimpleAction actionAddKittenEF;
SimpleAction actAddKittenXAF;
public KittenViewController() : base()
{
TargetObjectType = typeof(Kitten);
TargetViewNesting = Nesting.Nested;
actAddKittenXAF = new SimpleAction(this, "Add via OS", "View");
actAddKittenXAF.Execute += actAddKittenXAF_Execute;
actionAddKittenEF = new SimpleAction(this, "Add via Db", "View");
actionAddKittenEF.Execute += actionAddKittenEF_Execute;
}
private void actionAddKittenEF_Execute(object sender, SimpleActionExecuteEventArgs e)
{
var cat = View.ObjectSpace.GetObject(((NestedFrame)Frame).ViewItem.CurrentObject) as Cat;
var db = Helpers.MakeDb();
var kitten = new Kitten
{
Parent = db.Cats.FirstOrDefault(c => c.Id == cat.Id),
Name = $"baby {cat.Kittens.Count + 1} of {cat.Name}"
};
db.Kittens.Add(kitten);
db.SaveChanges();
View.ObjectSpace.Refresh();
}
//Errors
private void actAddKittenXAF_Execute(object sender, SimpleActionExecuteEventArgs e)
{
var cat = View.ObjectSpace.GetObject(((NestedFrame)Frame).ViewItem.CurrentObject) as Cat;
var os = View.ObjectSpace;
var kitten = os.CreateObject<Kitten>();
kitten.Parent = cat;
kitten.Name = $"baby {cat.Kittens.Count + 1} of {cat.Name}";
View.ObjectSpace.CommitChanges();
View.ObjectSpace.Refresh();
}
}
}

Cascading delete on a Entity Framework Child that requires Either Parents but not both

I have two classes that have a one to Many relationship to the child. The child can have only one parent, never both.
How can I make this possible? and if so how can I make it cascade delete if either parent get deleted?
class Parent1
{
public int Id {get;set;}
public IList<Child> Children {get;set;}
}
class Parent2
{
public int Id {get;set;}
public IList<Child> Children {get;set;}
}
class Child
{
public int Id {get;set;}
public int? Parent1Id {get;set;}
public int? Parent2Id {get;set;}
}
You can set a Entity Validation in EF to check this, but you also need to create a CHECK CONSTRAINT in your database to ensure that the rule is actually enforced.
Also you must have both FK properties and Navigation Properties on the Child entity to enforce this through EF. On a new Child the Navigation properties could be non-null, but the FK properties haven't been populated yet. On an existing entity, the FK properties will be loaded, but the Navigation Properties might not be. EG
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ef62test
{
class Program
{
public class Parent1
{
public int Id { get; set; }
public virtual ICollection<Child> Children { get; } = new HashSet<Child>();
}
public class Parent2
{
public int Id { get; set; }
public virtual ICollection<Child> Children { get; } = new HashSet<Child>();
}
public class Child
{
public int Id { get; set; }
public int? Parent1Id { get; set; }
public virtual Parent1 Parent1 { get; set; }
public int? Parent2Id { get; set; }
public virtual Parent2 Parent2 { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Parent1> Parent1s { get; set; }
public DbSet<Parent2> Parent2s { get; set; }
public DbSet<Child> Children { get; set; }
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var errors = new List<DbValidationError>();
if (entityEntry.Entity is Child child )
{
if ((child.Parent1Id != null || child.Parent1 != null)
&& (child.Parent2Id != null || child.Parent2 != null))
{
var error = new DbValidationError("Parent2id", "Parent2id must be null when Parent1id is null");
errors.Add(error);
}
}
return new DbEntityValidationResult(entityEntry, errors);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());
using (var db = new MyDbContext())
{
db.Database.Log = s => Console.WriteLine(s);
var p1 = new Parent1();
var p2 = new Parent2();
var c = new Child();
p1.Children.Add(c);
p2.Children.Add(c);
db.Parent1s.Add(p1);
db.Parent2s.Add(p2);
db.Children.Add(c);
db.SaveChanges();
}
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
}

deleted child entity generate wrong query?

the following code
using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
using System.Reflection;
namespace testef {
public class Order {
public Int32 Id { get; set; }
public String O { get; set; }
public virtual ICollection<OrderDetail> Details { get; set; }
}
public class OrderDetail {
public virtual Order Order { get; set; }
public Int32 Id { get; set; }
public String D { get; set; }
public Boolean IsActive { get; set; }
}
public class OrderDetailConfiguration : EntityTypeConfiguration<OrderDetail> {
public OrderDetailConfiguration()
: base() {
HasRequired(d => d.Order).WithMany(o => o.Details);
}
}
public class TestEFContext : DbContext {
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> Details { get; set; }
public TestEFContext(String cs)
: base(cs) {
Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
//Database.SetInitializer<TestEFContext>(null);
//Database.SetInitializer<TestEFContext>(new CreateDatabaseIfNotExists<TestEFContext>());
//Database.SetInitializer<TestEFContext>(new CustomDataBaseInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new OrderDetailConfiguration());
}
}
public class CustomDataBaseInitializer : CreateDatabaseIfNotExists<TestEFContext> {
public CustomDataBaseInitializer() : base() {
}
}
class Program {
static void Main(string[] args) {
String cs = #"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
using (TestEFContext ctx = new TestEFContext(cs)) {
Order o = new Order {
O = "O1",
Details = new List<OrderDetail>{
new OrderDetail { D = "D11", IsActive = true},
new OrderDetail { D = "D12", IsActive = false}
}
};
ctx.Orders.Add(o);
ctx.SaveChanges();
}
using (TestEFContext ctx = new TestEFContext(cs)) {
//OrderDetail d = new OrderDetail { Id = 1};
//ctx.Details.Attach(d);
OrderDetail d = ctx.Details.Where(x => x.Id == 1).First();
ctx.Details.Remove(d);
ctx.SaveChanges();
// ==> exec sp_executesql N'DELETE [dbo].[OrderDetails] WHERE (([Id] = #0) AND ([Order_Id] = #1))',N'#0 int,#1 int',#0=1,#1=1
}
}
}
}
generate following sql:
exec sp_executesql N'DELETE [dbo].[OrderDetails] WHERE (([Id] = #0) AND ([Order_Id] = #1))',N'#0 int,#1 int',#0=1,#1=1
I can't figure out why AND ([Order_Id] = #1. For me as the PK is Id a WHERE on Id must be enough!
Where am I wrong ?
It's a design decision the team made. I wouldn't consider either your stance or the EF teams tactic wrong...just choices. Both have benefits. I wouldn't get hung up on it, partially because deleting is uncommon in most applications, partially because there's an easy work around if performance is an issue.
If you want to execute just one query, do something like this:
ctx.Database.ExecuteSqlCommand("delete from [dbo].[OrderDetails] where Id = #p0", 1);

How to use Include method in LINQ To Entity when not sure that it has the specified navigation property?

I give you a CF example:
public class MyContext : DbContext
{
public DbSet<A> A { get; set; }
}
public class A
{
public int E { set; get; }
}
public class B : A
{
public int F { set; get; }
}
public class C : A
{
public int G { set; get; }
public virtual D D { set; get; }
}
public class D { }
and the query is like this:
using (var context = new MyContext())
{
var queryResult = context.A.Include("D").Select(a => a);
}
and it throws an exception with this message:
A specified Include path is not valid. The EntityType 'A' does not
declare a navigation property with the name 'D'.
How would you solve this with only one LINQ To Entity query?
Here is a work around
using (var context = new MyContext())
{
var typeA=typeOf(A);
var queryResult ;
if( typeA.GetProperty("D")!=null)
queryResult = context.A.Include("D").Select(a => a);
}

EF4 and UnitOfWork - How to make custom properties work

Say I have:
public class A
{
public virtual int Id { get; set; }
}
public class ARepository
{
private SomeContext _context;
public ARepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
}
public A GetAById(int aId)
{
return _context.A.Where(o => o.Id == aId).SingleOrDefault();
}
}
public class B
{
public virtual int Id { get; set; }
public virtual Category Category { get ; set; } //enum with NEW and OLD values
public virtual int Quantity { get; set; }
}
public class BRepository
{
private SomeContext _context;
public BRepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
}
public B GetBById(int bId)
{
return _context.B.Where(o => o.Id == bId).SingleOrDefault();
}
}
And I'm working with Entity Framework (4.1 code first).
How would I implement for example a custom property in A class like:
//returns the total of all B objects in the context where the category is NEW
public int NewBTotals
{
}
And not having to create a context?
Hopefully my question is clear enough, if not please let me know and I'll try to be more descriptive of what I want to achieve (ran out of time).
I found that even by B not having a foreign key to A, I can create a navigation property from A to B and vice versa which kind of solves the problem on its own.