2

私はこのようなクラスコースを持っています:

public class course   
{
        public int CourseID { get; set; }
        public string Name { get; set; }   
        public Event Schedule {get; set;} //Event is coming from library Dday.iCal  
}     

エンティティ フレームワークは、このプロパティを保存する方法を正しく認識できません。(保存時に文字列にシリアル化し、アプリケーションで使用するときにイベントとして保持したい。)したがって、SerializeToString()とDeserializeFromString()の2つのメソッドがあります。データベースに保存するときにのみこれらのメソッドを適用したい。

思いついたのは以下。基本的に、データベースに保存される文字列として別のプロパティを作成しようとしていますが、イベントは無視されますが、データベースには何も保存されません。これが物事を行うための良いアプローチなのか、それとももっと良いことができるのかさえわかりません.:

 public class course   
    {
            public int CourseID { get; set; }
            public string Name { get; set; }  
            private Event _Schedule;
            [NotMapped]  
            public Event Schedule {  
            get
            {
                if (!String.IsNullOrEmpty(CourseSchedule))
                {
                    return DeserilizeFromString(CourseSchedule);
                }
                return new Event();
            }
            set
            {
                _schedule = value;
            }
            }  
            private string _courseSchedule;
            public string CourseSchedule { 
            get
            {
                return _courseSchedule;
            }
            private set
            {
                if (Schedule != null)
                {
                    _courseSchedule = SerializeToString(Schedule);
                }
                else
                {
                    _courseSchedule = null;
                }
            }   
 }
4

4 に答える 4

1

asp.netの作成者は、実際には、あなたがやろうとしていることをほぼ完全に実装しています。あなたはあなたが始めるためにそのプロジェクトのいくつかのポイントに従うことを望むかもしれません。プロジェクトへのリンクはこちらです。

注意すべき点はDbContext Api、EntityFrameworkで実装されたものを利用していることです。上記の抽象化のいくつかは次のようなものです。

あなたの解決策:

  • モデル
  • 意見
  • コントローラ
  • データアクセス層(DAL)

チュートリアルでは、実際には、、、およびを使用して実装を行いCourse Controllerます。チュートリアルの終わりまでに、これらを実装し、次のようになります。Unit Of Work ClassRepositoriesautomatic propertiesDbContext

// Model:
public abstract class Person
    {
        [Key]
        public int PersonID { get; set; }

        [Required(ErrorMessage = "Last name is required.")]
        [Display(Name = "Last Name")]
        [MaxLength(50)]
        public string LastName { get; set; }

        [Required(ErrorMessage = "First name is required.")]
        [Column("FirstName")]
        [Display(Name = "First Name")]
        [MaxLength(50)]
        public string FirstMidName { get; set; }

        public string FullName
        {
            get
            {
                return LastName + ", " + FirstMidName;
            }
        }
    }

// Repository:
public class StudentRepository : IStudentRepository, IDisposable
    {
        private SchoolContext context;

        public StudentRepository(SchoolContext context)
        {
            this.context = context;
        }

        public IEnumerable<Student> GetStudents()
        {
            return context.Students.ToList();
        }

        public Student GetStudentByID(int id)
        {
            return context.Students.Find(id);
        }

        public void InsertStudent(Student student)
        {
            context.Students.Add(student);
        }

        public void DeleteStudent(int studentID)
        {
            Student student = context.Students.Find(studentID);
            context.Students.Remove(student);
        }

        public void UpdateStudent(Student student)
        {
            context.Entry(student).State = EntityState.Modified;
        }

        public void Save()
        {
            context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

// Interface for Repository:
    public interface IStudentRepository : IDisposable
    {
        IEnumerable<Student> GetStudents();
        Student GetStudentByID(int studentId);
        void InsertStudent(Student student);
        void DeleteStudent(int studentID);
        void UpdateStudent(Student student);
        void Save();
    }

// Context to Generate Database:
    public class SchoolContext : DbContext
    {
        public DbSet<Course> Courses { get; set; }
        public DbSet<Department> Departments { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Instructor> Instructors { get; set; }
        public DbSet<Student> Students { get; set; }
        public DbSet<Person> People { get; set; }
        public DbSet<OfficeAssignment> OfficeAssignments { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            modelBuilder.Entity<Instructor>()
                .HasOptional(p => p.OfficeAssignment).WithRequired(p => p.Instructor);
            modelBuilder.Entity<Course>()
                .HasMany(c => c.Instructors).WithMany(i => i.Courses)
                .Map(t => t.MapLeftKey("CourseID")
                    .MapRightKey("PersonID")
                    .ToTable("CourseInstructor"));
            modelBuilder.Entity<Department>()
                .HasOptional(x => x.Administrator);
        }
    }

// Unit Of Work
public class UnitOfWork : IDisposable
    {
        private SchoolContext context = new SchoolContext();
        private GenericRepository<Department> departmentRepository;
        private CourseRepository courseRepository;

        public GenericRepository<Department> DepartmentRepository
        {
            get
            {

                if (this.departmentRepository == null)
                {
                    this.departmentRepository = new GenericRepository<Department>(context);
                }
                return departmentRepository;
            }
        }

        public CourseRepository CourseRepository
        {
            get
            {

                if (this.courseRepository == null)
                {
                    this.courseRepository = new CourseRepository(context);
                }
                return courseRepository;
            }
        }

        public void Save()
        {
            context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }

これはレッスンの内容の一部です。抽象化が機能する理由を理解しながら、質問にかなり明確に答えることができると思います。これは、を実装しているためFluent Apiです。

お役に立てば幸いです。

于 2013-02-05T20:39:40.367 に答える
0

おそらく、このロジックに抽象化を導入することで、作業単位とリポジトリパターンを再作成し、より便利な方法で目的のロジックを追加できます。たとえば、Courseリポジトリクラスでは、イベントフィールドをシリアル化および逆シリアル化するaddおよびfindメソッドをコスチューム化できます。

リポジトリパターンに焦点を当てます。Web上のデータアクセス層全体の設計に関する多くの情報を見つけることができます。

たとえば、コースを管理するには、アプリケーションが次のようなICourseRepositoryインターフェイスに依存している必要があります。

interface ICourseRepository
{
    void Add(Course newCourse);
    Course FindByID(int id);
}

そして、次の実装を提供します。

class CourseRepository
{
    // DbContext and maybe other fields

    public void Add(Course c)
    {

        // Serialize the event field before save the object
        _courses.Add(c);   // calling entity framework functions, note  
                           // that '_courses' variable could be an DBSet from EF
    }

    public Course FindById(int id)
    {
       var course = /// utilize EF functions here to retrieve the object
       // In course variable deserialize the event field before to return it ...
    }
}

EFのObjectContextはこのパターンの実装であることに注意してください。将来、ORMを変更するつもりがない場合は、EFのSaveメソッドをオーバーライドするだけです。

この種のパターンについて詳しく知りたい場合は、MartinFowlerのサイトにアクセスしてください。

于 2013-02-05T20:20:37.010 に答える
0

自動プロパティと属性だけで、モデルをできるだけ最小限に保つ必要があります。より複雑なビジネス ロジックについては、MVC パターンに別のレイヤーを追加することをお勧めします。これは通常、Repository と呼ばれます (ただし、Repository パターンに関する適切なチュートリアルを見つけるのは難しい.. :( ) モデルとコントローラー コントローラーの間にあります。

これは単体テストの実行にも非常に役立ちます。適切に実装すると、テスト中にデータベースの依存関係をコレクションに置き換えることができます。このアプローチでは、プロジェクトでさらに多くの作業が必要になります。

もう 1 つのアプローチ (より単純なアプローチ) は、ViewModel レイヤーを追加することです。このようにしてください:

class MyModel
{
    public string Text { get; set; }
}

class MyViewModel : MyModel
{
    public new string Text
    {
        get { return base.Text; }
        set { base.Text =value.ToUpper(); }
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyViewModel mvm = new MyViewModel();
        mvm.Text = "hello there";
        var s = ((MyModel) mvm).Text; // "HELLO THERE"
    }
}

DataContext では、コントローラーで MyModel を使用し、MyViewModel を使用します。

于 2013-02-05T20:28:06.153 に答える
0

こんな感じのモデルがあれば

using (LolEntities context = new LolEntities)
{
...
}

アプリケーションのどこかに、このモデルが定義されています。通常は次のようになります。

public partial class LolEntities : ObjectContext

(1) このクラスは部分クラスであるため、同じ名前とオーバーライドで別の部分クラスを作成できます。

public override int SaveChanges(SaveOptions options)

(2) または、イベントをキャプチャすることもできます。

using (DemoAZ_8_0Entities context = new DemoAZ_8_0Entities())
{
    context.SavingChanges += ...
}

DBに送り返される前にフォーマットを行います。

モデルには、DB の列に適切にマップされるプロパティを必ず含めてください。

于 2013-02-05T20:15:53.880 に答える