C# zapisywanie obiektu w bazie danych

0

Witam.
W jaki sposób mogę wysyłać i zapisywać w bazie danych MySQL własne obiekty napisane w c#? Czy muszę skorzystać do tego celu z jakiegoś mechanizmu mapowania obiektowo-relacyjnego np Entity Framework?

3

Możesz skorzystać z wbudowanego ADO albo jakiegoś ORM'a. Najbliższy czystemu SQL'owi jest Dapper.

0
grzesiek51114 napisał(a):

Możesz skorzystać z wbudowanego ADO albo jakiegoś ORM'a. Najbliższy czystemu SQL'owi jest Dapper.

Mógłbyś podesłać jakiś kod jak to zrobić za pomocą ADO? Jakie rozwiązanie jest lepsze(ADO czy ORM) czy może obojętnie którą technologię wybiorę?

1

ADO, skądś tam:

 string connString = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
 using (var conn = new MySqlConnection(connString))
 {
      conn.Open();
      var comm = conn.CreateCommand();
      comm.CommandText = "INSERT INTO room(person,address) VALUES(@person, @address)";
      comm.Parameters.AddWithValue("?person", "Myname");
      comm.Parameters.AddWithValue("?address", "Myaddress");
      comm.ExecuteNonQuery();
  }

Dapper: cały crud: https://stackoverflow.com/questions/5957774/performing-inserts-and-updates-with-dapper

Samemu nie chce mi się tego pisać. Przykładów w sieci jest naprawdę mnóstwo.

A która technologia lepsza to zależy co chcesz robić. Mnie się w ADO nie chce bawić, zresztą Dapper jest wraperem na ADO. :-)

3
komor98 napisał(a):

Jakie rozwiązanie jest lepsze(ADO czy ORM) czy może obojętnie którą technologię wybiorę?

Zależy ile masz tych klas, jak często zmienia się struktura, czy baza danych już istnieje, jaki to rodzaj aplikacji, i jaka jest częstotliwość zapisywania obiektów.
Jeśli dopiero zaczynasz pisanie aplikacji, więc klas będzie dużo i często się będą zmieniały, i do tego jest to typowy CRUD, do którego dane wprowadzają ludzie, to wygodniej będzie użyć ORM - bazę danych wygeneruje się z kodu, a dodatkowy narzut na mapowanie obiektowo-relacyjne nie będzie miał wpływu na końcową wydajność systemu. Pojedyncze czasochłonne operacje i tak będzie można zrobić za pomocą SQL (np. procedur składowanych). ORM dodatkowo może dać różne dodatkowe możliwości, np. automatyczny audyt rekordów, które bez ORMa trzeba pisać po swojemu.
Jeśli klas jest mało i nie mają zmiennej struktury, to możesz użyć ADO, bo więcej zajmie Ci konfigurowanie ORMa niż napisanie zapytań.
Jeśli to CRUD, ale baza już istnieje, to wystarczy jakiś mikroorm typu Dapper.

0

Udało mi się serializować mój obiekt i wysłać go za pomocą ADO do bazy danych MySQL. Jaki typ powinno mieć pole przechowujące taki obiekt? Jeśli ustawię na binary to nie zapisuje obiektu a jeżeli na varchar to przy odczycie wywala, że nieprawidłowy typ

0

A czemu chcesz trzymać zserializowane obiekty w bazie? Nie będziesz chciał ich wyszukiwać ani filtrować?

0

W jaki sposób mogę to zrobić bez serializacij? Przypisać po prostu obiekt do danego pola w tabeli?

2

Zapisać obiekt jako wiersz w tabeli, czyli zmapować pola obiektu na kolumny tabeli, czyli napisać taki SQL insert jaki podał Ci @grzesiek51114 parę postów wyżej.

0

Robię sobie teraz relacje w NHibernate jeden do wielu

 public class Customer
    {
        public Customer()
        {
           // MemberSince = DateTime.UtcNow;
            Orders = new HashSet<Order>();
        }

        public virtual Guid Id { get; set; }
        public virtual string Imie { get; set; }
        public virtual string Nazwisko { get; set; }
        public virtual double AverageRating { get; set; }
        public virtual int Points { get; set; }

        public virtual bool HasGoldStatus { get; set; }
       // public virtual DateTime MemberSince { get; set; }
        public virtual CustomerCreditRating CreditRating { get; set; }
        public virtual Location Address { get; set; }// <-----

        public virtual ISet<Order> Orders { get; set; }

        public virtual void AddOrder(Order order)
        {
            Orders.Add(order);
            order.Customer = this;
        }


        public override string ToString()
        {
            var result = new StringBuilder();

           // result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:{ 4}\r\n\tMemberSince: { 5} ({ 7})\r\n\tCreditRating: { 6}\r\n\tAverageRating:{ 8}\r\n",
             //   Id, Imie, Nazwisko, Points, HasGoldStatus, MemberSince, CreditRating, MemberSince.Kind, AverageRating);
           // result.AppendLine("\tOrders:");

            foreach (var order in Orders)
            {
                result.AppendLine("\t\t" + order);
            }

            return result.ToString();
        }


    }

    public class Location
    {
        public virtual string Street { get; set; }
        public virtual string City { get; set; }
        public virtual string Province { get; set; }
        public virtual string Country{ get; set; }
    }

    public enum CustomerCreditRating
    {
        Excelent,
        VeryGood,
        Good
    }
 public class Order
    {
        public virtual Guid Id { get; set; }
        public virtual DateTime Ordered { get; set; }
        public virtual DateTime? Shipped { get; set; }
        public virtual Location ShipTo { get; set; }
        public virtual Customer Customer { get; set; }

        public override string ToString()
        {
            return string.Format("Order Id: {0}", Id);
        }
    }
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "Test_NHibernate"
   namespace = "Test_NHibernate">

  <class name = "Customer">

    <id name = "Id">
      <generator class = "guid.comb"/>
    </id>

    <property name = "Imie"/>
    <property name = "Nazwisko"/>
    <property name = "AverageRating"/>
    <property name = "Points"/>
    <property name = "HasGoldStatus"/>
    <!-- <property name = "MemberSince" type = "UtcDateTime"/> -->
    <property name = "CreditRating" />  <!--  column="CreditRating" type = "CustomerCreditRatingType"  -->

    <component name = "Address">
      <property name = "Street"/>
      <property name = "City"/>
      <property name = "Province"/>
      <property name = "Country"/>
    </component>

  </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "Test_NHibernate"
   namespace = "Test_NHibernate">

  <class name = "Order" table = "Order">

    <id name = "Id">
      <generator class = "guid.comb"/>
    </id>

    <property name = "Ordered"/>
    <property name = "Shipped"/>

    <component name = "ShipTo">
      <property name = "Street"/>
      <property name = "City"/>
      <property name = "Province"/>
      <property name = "Country"/>
    </component>

    <!--<many-to-one name = "Customer" column = "CustomerId" cascade =
         "save-update"/>-->

  </class>
</hibernate-mapping>
 private void RelacjeBtn_Click(object sender, RoutedEventArgs e)
        {
            var cfg = new Configuration();
                       
            
            cfg.DataBaseIntegration(x =>
            {
                x.ConnectionString = "server=localhost;user=root; password=fajnabmw123;database=bazaNHibernate";
                x.Driver<MySqlDataDriver>();
                x.Dialect<MySQL5Dialect>();
                x.IsolationLevel = IsolationLevel.RepeatableRead;
                x.Timeout = 10;
                x.BatchSize = 10;

            });

            cfg.SessionFactory().GenerateStatistics();
            cfg.AddAssembly(Assembly.GetExecutingAssembly());

            var sessionFactory = cfg.BuildSessionFactory();

            Guid id;
            using (var session = sessionFactory.OpenSession())

            using (var tx = session.BeginTransaction())
            {
                var newCustomer = CreateCustomer();
                session.Save(newCustomer);
                id = newCustomer.Id;
                tx.Commit();
            }

            using (var session = sessionFactory.OpenSession())

            using (var tx = session.BeginTransaction())
            {
                var reloaded = session.Load<Customer>(id);
                Console.WriteLine("Reloaded:");
                Console.WriteLine(reloaded);
                tx.Commit();
            }



        }



        private static Customer CreateCustomer()
        {

            var customer = new Customer
            {
                Imie = "John",
                Nazwisko = "Doe",
                Points = 100,
                HasGoldStatus = true,
                //MemberSince = new DateTime(2012, 1, 1),
                CreditRating = CustomerCreditRating.Good,
                AverageRating = 42.42424242,
                Address = CreateLocation()
            };

            var order1 = new Order
            {
                Ordered = DateTime.Now
            };

            customer.AddOrder(order1);

            var order2 = new Order
            {
                Ordered = DateTime.Now.AddDays(-1),
                Shipped = DateTime.Now,
                ShipTo = CreateLocation()
            };

            customer.AddOrder(order2);
            return customer;
        }

        private static Location CreateLocation()
        {

            return new Location
            {
                Street = "123 Somewhere Avenue",
                City = "Nowhere",
                Province = "Alberta",
                Country = "Canada"
            };
        }

Mam taki problem, że dodaje nowy rekord tylko do tabeli Customer a tabela Order jest pusta. Co może być nie tak?

3

O Borze Tucholski, 2018 rok on w XML pisze... :|
Użyj FluentNHibernate i zmapuj to jak człowiek.

0

Dzięki wielkie za podpowiedź, nawet nie wiedziałem, że coś takiego jest :)
Przy okazji mam pytanie czy dobrze skonfigurowałem fluenta pod MySQL?

namespace Test_Fluent_Nhibernate
{
    public class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;
        

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null) InitializeSessionFactory();
                return _sessionFactory;
            }
        }


        private static void InitializeSessionFactory()
        {
            var dbServer = "localhost";
            var dbUserName = "root";
            var dbName = "bazaFluentNHibernate";
            var dbPassword = "fajnabmw123";
            var ormAssembly = "Test_Fluent_Nhibernate"; //tu moze byc blad

            _sessionFactory = Fluently.Configure()
                .Database(MySQLConfiguration.Standard.ConnectionString(cs => cs
                                                                             .Server(dbServer)
                                                                             .Database(dbName)
                                                                             .Username(dbUserName)
                                                                             .Password(dbPassword)))
                         .Mappings(
                            x =>
                            x.FluentMappings.AddFromAssembly(Assembly.Load(ormAssembly))).BuildSessionFactory();
            //return config.BuildConfiguration();


        }


        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }


    }
}

I przy takim mapowaniu jaki typ powinienem ustawić(tam gdzie są relacje) dla kolumn tabel w bazie danych?

namespace Test_Fluent_Nhibernate.Mappings
{
    public class StoreMap : ClassMap<Store>
    {
        public StoreMap()
        {
            Id(x => x.Id);
            Map(x => x.Name);
            HasMany(x => x.Staff)
              .Inverse()
              .Cascade.All();
            HasManyToMany(x => x.Products)
             .Cascade.All()
             .Table("StoreProduct");
        }
    }

public class ProductMap : ClassMap<Product>
    {
        
        public ProductMap()
        {
            Id(x => x.Id);
            Map(x => x.Name);
            Map(x => x.Price);
            HasManyToMany(x => x.StoresStockedIn)
              .Cascade.All()
              .Inverse()
              .Table("StoreProduct");
        }
    }

 public class EmployeeMap : ClassMap<Employee>
    {

        public EmployeeMap()
        {
            Id(x => x.Id);
            Map(x => x.FirstName);
            Map(x => x.LastName);
            References(x => x.Store);
        }

    }

}

1 użytkowników online, w tym zalogowanych: 0, gości: 1